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

时间:2015-05-26 11:40:07

标签: c 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(垃圾值)。

4 个答案:

答案 0 :(得分:2)

根据C11标准,章节§6.3.2.3

  

整数可以转换为任何指针类型。除非事先指明,否则   结果是实现定义的,可能没有正确对齐,可能不指向   引用类型的实体,可能是陷阱表示。

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

在这种特殊情况下,您将b作为参数传递给scanf()未初始化,这将导致程序调用{​​{3}} ,一旦执行。

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

答案 1 :(得分:1)

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

编译器希望你给出一个有效的地址来扫描值,在运行时只会知道地址是否有效。

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

答案 2 :(得分:1)

它扫描正常,因为scanf期望其参数中有一个内存位置。这就是我们使用&给出相应变量的内存位置的原因。

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

答案 3 :(得分:0)

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