为什么编译器在将 int(不是 int *)作为 scanf() 的参数传递时不发出错误?

Why compiler is not issuing error while passing an int (not int *) as the argument of scanf()?

我尝试了下面的 c 程序,我预计会出现编译时错误,但为什么编译器没有给出任何错误?

#include <stdio.h>
#include <conio.h>
int main() 
{
  int a,b;
  printf("Enter a : ");
  scanf("%d",&a);
  printf("Enter b : ");
  scanf("%d",b);
  printf("a is %d and b is %d\n",a,b);
  getch();
  return 0;
}

我不是在scanf("%d",b)中写&。在编译时,编译器不会给出任何错误,但在执行期间 b 的值是 2686792(垃圾值)。

根据 C11 标准,章节 §6.3.2.3

An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.

因此,编译器将允许这样做,但结果是实现定义的。

在这种特殊情况下,您将 b 作为参数传递给 scanf(),它是 未初始化的 ,这将导致程序调用undefined behaviour,一次执行。

此外,printf() / scanf() 是可变参数函数,通常不检查参数 type ,除非通过编译器标志明确询问 [参见-Wformat].

这不是编译时错误,而是运行时问题。

编译器希望您提供一个有效的地址来扫描值,只有在运行时它才会知道地址是否有效。

如果您尝试将值扫描到无效地址,则会导致未定义的行为并可能会发生崩溃。

它扫描得很好,因为 scanf 期望在其参数中有一个内存位置。这就是为什么我们使用 & 来给出相应变量的内存位置。

在你的情况下 scanf 只是扫描输入的值并将其放入值为 b 的内存位置(而不是扫描并将其放入 b 被存储)。

C中的&运算符returns操作数的地址。如果只给出 b 而没有 & 运算符,它将按值传递并且 scanf 将无法设置值。正如您已经注意到的那样,这将导致意外行为。它无法在运行时之前验证地址,因此您直到运行时才会注意到这个问题。