0

For the following, I can use a pointer or a char array for scanf:

char name[10];
printf("Please enter your name: ");
scanf("%9s", name);

And I could also do:

char *name = (char*)malloc(10)
printf("Please enter your name: ");
scanf("%9s", name);

The second one is obviously a char* pointer, but the first one is not -- it is an array. Why, if it's not an array and scanf expects a pointer am I able to do scanf("%9s", name) and not be forced to do scanf("%9s", &name)?

samuelbrody1249
  • 4,379
  • 1
  • 15
  • 58
  • _but the first one is not_ , your assumption is wrong, in `C` name = &name[0] – IrAM Jan 08 '21 at 03:17
  • When used in an expression context, an array id implicitly converts to a temporary pointer-to-type value, where the type is that of the underlying array, and the value is the address of the first element within the array. In the first example `&name` is a different type, btw. It is `char (*)[10]`, a pointer to an array of 10 char. The same syntax in the second example would yield a completely different type (pointer to pointer to char). – WhozCraig Jan 08 '21 at 03:20
  • 3
    See [What is array to pointer decay?](https://stackoverflow.com/questions/1461432/what-is-array-to-pointer-decay). – dxiv Jan 08 '21 at 03:24
  • @tadman, just to clarify. Even if c doesn't differentiate between pointers and arrays exactly the same way as humans do, it absolute positively *do* differentiate between pointers and arrays. – HAL9000 Jan 08 '21 at 03:31
  • @HAL9000 Oh, it does, but just not in ways that make intuitive sense. It sees them from a completely different angle. – tadman Jan 08 '21 at 03:31
  • @tadman, seeing your reputation score, I totally assume you are aware of all the internal details of arrays and pointers. But answers here are also for other readers. And sadly, there is often a misconception that pointers and arrays in c are the same. – HAL9000 Jan 08 '21 at 03:40
  • @Iram, if `name` is an array, then `name` is not always equivalent to `&name[0]`. For instance `sizeof(name)` may not be the same as `sizeof(&name[0])`. But in a context expecting a pointer-value, then yes, they should be the same. – HAL9000 Jan 08 '21 at 03:45
  • @tadman, as seen by this post, saying that pointers and arrays are largely interchangeable is not a good "level 1" explanation. Other than that I agree to what you are trying to say. There is a lot of c/c++ explanations that are to pedantic with their definitions, ignoring what could be a good mental model. But arrays equaling pointers is not one of them. – HAL9000 Jan 08 '21 at 03:59
  • Does this answer your question? [What is array to pointer decay?](https://stackoverflow.com/questions/1461432/what-is-array-to-pointer-decay) – tadman Jan 08 '21 at 04:25

2 Answers2

2

Except when it is the operand of the sizeof or unary & operators, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T" will be converted, or "decay", to an expression of type "pointer to T" and the value of the expression is the address of the first element of the array.

This is true of all array types, not just character arrays.

So when you write

scanf("%9s", name);

the expression name is converted from type "10-element array of char" to "pointer to char", and what scanf receives is the address of the first element of the array.

This is important - arrays are not pointers; array expressions are converted to pointers as necessary.

Believe it or not, there is a reason for this behavior. C was derived from an earlier language called B. In B, array objects had an explicit pointer to the first element, and the subscript operation a[i] was defined as *(a + i) - given a starting address a, offset i elements from that address and dereference the result.

When designing C, Ritchie wanted to keep B’s array semantics, but he didn’t want to keep the explicit pointer to the first element that those semantics required. So instead of creating storage for the pointer, he created the rule that the array expression is converted to a pointer expression when necessary.

And this is why arrays are weird.

John Bode
  • 119,563
  • 19
  • 122
  • 198
0

When using "%9s" as format specifier, scanf doesn't "take a pointer or an array". It only takes a pointer. What happens when you give it an array, is that the compiler does some magic. It creates a pointer to the first element of the array and gives that to scanf. So this two snippets of code are equivalent:

/* Snippet A */
char name[10];
scanf("%9s", name);

/* Snippet B */
char name[10];
scanf("%9s", &name[0]);

This does not only happen for scanf, but virtually every time something expects a pointer and you give it an array. A notable place where it doesn't happen, is with the sizeof operator.

HAL9000
  • 2,138
  • 1
  • 9
  • 20