缺少访问说明符&;在C中不会导致编译错误

缺少访问说明符&;在C中不会导致编译错误,c,string,pass-by-reference,access-specifier,C,String,Pass By Reference,Access Specifier,在C语言中,当scanf()中的参数缺少&时,不会产生编译错误;相反,显示的结果是错误的(即出现语义错误) 考虑以下代码: char str[30]; int a; printf("Enter the value"); scanf("%s %d", str, a); // This is the statement in question. printf("You entered %s %d", str, a); 这里我知道str是一个字符数组,因此它有一个基址,因此不会产生编译错

在C语言中,当
scanf()
中的参数缺少
&
时,不会产生编译错误;相反,显示的结果是错误的(即出现语义错误)

考虑以下代码:

char str[30];
int a;
printf("Enter the value");
scanf("%s %d", str, a);       // This is the statement in question.
printf("You entered %s %d", str, a);
这里我知道
str
是一个字符数组,因此它有一个基址,因此不会产生编译错误。但是为什么参数
a
缺少
&
不会导致编译错误呢

同样,
str
给出正确的输出,但是整数总是产生值-28770,作为输出。为什么会这样

int scanf(const char *format, ...);

这是scanf的原型。第一个参数是char*,其他参数是可变长度。因此不会生成错误。

正如Umamahesh p所写,您不会得到编译错误,因为scanf是一个变量参数函数。至于运行程序时会发生什么,C标准称之为“未定义的行为”。任何事情都有可能发生。您需要查看机器指令和内存地址级别上发生的情况,以查看scanf对您给定的整数值(而不是指针)的具体操作。

scanf
具有以下原型:

int scanf(const char *fmt, ...);

表示可以在
fmt
之后指定任意数量的任何类型的参数。因此,调用者(而不是编译器)有责任确保提供的参数与函数预期的参数匹配。

您可能会收到编译器警告,具体取决于您使用的编译器和指定的选项

此外,即使它试图显示这些警告,如果使用vscanf()或使用动态字符串作为格式参数,编译器也将完全无法执行

例如,这是我使用mingw-64 gcc 4.5.4获得的输出:

gcc -Wall -o small.exe small.c

small.c:7:3: warning: format '%d' expects type 'int *', but argument 3 has type 'int'
small.c:7:8: warning: 'a' is used uninitialized in this function

只需添加-Werror选项即可将这些警告变为错误。

您输入的是什么?您希望输出的是什么?“整数总是给出-28770作为输出”-未初始化的局部变量
a
。包含声明之前在该内存位置(堆栈或寄存器)的内容。每次运行可能相同,每次可能不同;这就是为什么它是“未定义的行为”你的编译器没有警告过你吗?好的。编译器并没有给出任何警告。感谢您的回答。详细说明一下:
scanf()
中的varargs没有声明的类型,因此,对于编译器来说,可以是绝对任何类型。难道
scanf(…,a)
甚至不会尝试将值输入写入内存中的随机位置,可能会发生segfaulting?@HannoBinder-但行为尚未定义,这意味着任何事情都有可能发生。@HannoBinder:正如davmac所写,这是可能发生的,但不能保证。我看到的另一个行为是,参数在寄存器中传递,32位整数和64位指针在不同的寄存器中传递,因此scanf将获得一个指向某个恰好位于正确寄存器中的对象的指针。@ThomasPadron McCarthy感谢这一有趣的见解。