C中数组的运算符定义

Jes*_*ess 4 c arrays standards pointers

最近的一个问题引发了以数组和指针为中心的讨论.问题是参考scanf("%s", &name)VS scanf("%s", name).

对于以下代码,Microsoft实际上在VS2010(也许是早期版本?)中为您解决了这个问题,

#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;
}
Run Code Online (Sandbox Code Playgroud)

这实际上是在ANSI C标准中定义的,还是允许编译器相关的?这是否有效,因为MS将所有内容都视为C++?请暂时忽略缓冲区溢出问题.

Jam*_*lis 7

双方name&name应给予同样的结果.严格来说,只有name符合C语言标准才有效并&name导致未定义的行为,所以你绝对应该使用name,但实际上两者都有效.

name是一个数组,所以当你将它用作函数的参数时(就像你传递它时一样printf),它会"衰减"到指向其初始元素的指针(这是一个char*在这里).

&name给你数组的地址; 这个地址是相同的初始元素的地址(因为可以有一个阵列的或数组中的元素之间的初始元件之前没有填充字节),所以&namename具有相同的指针值.

但是,它们有不同的类型: &name类型char (*)[30](指向30的数组的指针char),而name当它衰减到指向其初始元素的指针时,是类型char*(指向a的指针char,在本例中是指向的初始char元素)数组name).

由于它们具有相同的价值,因为printfscanf功能重新诠释参数作为char*反正你是否传递不应该有差别name&name.

  • 实际上,你是绝对正确的.然而,值得一提的是,正式的不匹配会导致未定义的行为,因此最好省略它. (2认同)