& operator for arrays in C

A recent question has sparked a discussion about arrays and pointers. The question was about scanf("%s", &name) vs scanf("%s", name) .

For the following code, Microsoft actually resolves this for you in VS2010 (and possibly earlier versions?),

 #include <stdio.h> int main() { char name[30]; printf("Scan \"name\" - "); scanf("%s", name); printf("Print \"&name\" - %s\n", &name); printf("Print \"name\" - %s\n", name); printf("Pointer to &name - %p\n", &name); printf("Pointer to name - %p\n", name); printf("\n\n"); printf("Scan \"&name\" - "); scanf("%s", &name); printf("Print \"&name\" - %s\n", &name); printf("Print \"name\" - %s\n", name); printf("Pointer to &name - %p\n", &name); printf("Pointer to name - %p\n", name); return 0; } 

Is it actually defined in the ANSI C standard, or is it allowed to be compiler dependent? Does this work because MS treats everything as C ++? For now, ignore buffer overflow problems.

+4
source share
2 answers

Both name and &name should give the same result. Strictly speaking, only name valid for the standard C language, and &name leads to undefined behavior, so you should definitely use name , but in practice both will work.

name is an array, so when you use it as an argument to a function (as you do when you pass it to printf ), it "splits" into a pointer to its original element (which is char* here).

&name gives you the address of the array; this address matches the address of the original element (because there should be no padding bytes in front of the original element of the array or between elements in the array), therefore &name and name have the same pointer value.

However, they have different types: &name is of type char (*)[30] (a pointer to an array of 30 char ), and name , when it decays to a pointer to its source element, is of type char* (a pointer to char , in this case is the initial char element of the name array).

Since they have the same meaning, and since the printf and scanf functions will in any case reinterpret the argument as char* , there should be no difference whether you pass name or &name .

+7
source

Undefined Behavior as per standard.

The printf conversion specifier "%p" expects void* : everything else calls UB The printf "%s" transform specifier expects a char* that includes a null byte somewhere inside the object that it points to: everything else calls UB The scanf transform specifier "%s" expects char* with enough input space and an extra trailing byte: anything that calls UB

If any implementation defines the behavior, then it should be normal to use in this implementation .

Most often, printing char* or char(*)[30] instead of void* with printf("%p") results in a UB manifestation that is indistinguishable from the intended behavior.

Most often, printing char(*)[30] instead of char* with printf("%s") results in a UB manifest that is indistinguishable from the intended behavior.

From what you are saying, it looks like the UB MS manifest in these cases is the same as intended.

But this is still Undefined Behavior.

+2
source

All Articles