& operator definition for arrays in C

大兔子大兔子 提交于 2019-12-05 01:03:14

问题


A recent question prompted a discussion centering on arrays and pointers. The question was in reference to scanf("%s", &name) vs scanf("%s", name).

For the following code, Microsoft actually resolves this for you in VS2010 (and maybe 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 this actually defined in the ANSI C Standard, or is this allowed to be compiler dependent? Does this work because MS is treating everything as C++? Please ignore buffer overflow issues for now.


回答1:


Both name and &name should give the same result. Strictly speaking, only name is valid per the C language standard and &name results in 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 "decays" to a pointer to its initial element (which is a char* here).

&name gives you the address of the array; this address is the same as the address of the initial element (because there can be no padding bytes before the initial element of an array or between elements in an array), so &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) while name, when it decays to a pointer to its initial element, is of type char* (a pointer to a char, in this case, the initial char element of the array name).

Since they have the same value and since the printf and scanf functions reinterpret the argument as a char* anyway, there should be no difference whether you pass name or &name.




回答2:


Undefined Behaviour as per the Standard.

The printf conversion specifier "%p" expects a void*: anything else invokes UB The printf conversion specifier "%s" expects a char* that includes a null byte somewhere inside the object pointed to: anything else invokes UB The scanf conversion specifier "%s" expects a char* with enough space for the input and an extra null terminating byte: anything else invokes UB

If any implementation defines the behaviour, then it should be ok to use in that implementation.

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

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

From what you say, it appears MS manifestation of UB in these cases is the same as intended.

But it's still Undefined Behaviour.



来源:https://stackoverflow.com/questions/5851177/operator-definition-for-arrays-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!