变量的声明如何表现?

#include #include int main(){ char i; int c; scanf("%i",&c); scanf("%c",&i);// catch the new line or character introduced before x number printf("%i",i);// value of that character getch(); return(0); } 

程序将以与下一个变量声明相同的方式运行,而不是上述变量声明:

这个:

 int c; int *x; int i; 

或这个:

 int *x; int c; int i; 

并且只有这样: c变量和i变量之前的x指针。 我知道那些最后的声明没有意义, int i而不是char i ,以及一个甚至不需要的添加指针。 但这是偶然发生的,我想知道这是否只是一个巧合。

假设你的代码的其余部分没有任何问题,你声明变量的顺序应该没有任何区别。 声明的顺序不需要与它们在内存中的布局方式有任何关系。 即使它确实如此,你也可以通过名称来引用变量; 只要你的代码是正确的,对i的引用就是对i的引用,编译器将生成正确访问变量所需的任何代码。

现在,如果你这样做:

 int i; scanf("%c", &i); 

然后你做错了什么。 具有"%i"格式的scanf需要char*参数,该参数指向将存储值的char对象。 你给它一个int*而不是char* 。 结果,你的程序的行为是不确定的; 语言标准没有说明它将如何表现。

那为什么它似乎正常工作? 可能发生的是scanfint对象的地址视为指向char的指针。 它可能指向i的表示的第一个字节; 例如, i可能是32位,指针将指向这些位的前8位。 (它们可能是高阶或低阶位,具体取决于系统。)

现在当你打印i的值时:

 printf("%d\n", i); 

例如, i的内容是1个字节,由你刚刚读入它的任何字符和3个字节的垃圾组成。 这3个垃圾字节可能都是零,但它们可以是任何东西。 如果垃圾字节恰好是0,并且第一个字节恰好是高位字节(即,你在大端机器上),那么你很可能得到“正确”的输出。

但不要这样做。 由于行为未定义,它可以“正确”工作多年,然后在最糟糕的时刻失败。

这里的教训是,C倾向于认为你知道自己在做什么。 有许多构造具有未定义的行为,这意味着它们无效,但是编译器和运行时系统都不需要告诉您存在问题。 在C语言中,除了大多数其他语言之外,还有一个程序员能够把事情弄清楚。 编译器(和其他工具)将告诉您一些错误,但不是所有错误。

并且在存在未定义的行为时,声明变量的顺序可能会有所不同。 例如,如果您编写的代码读取或写入变量的末尾,那么存储在那里的内容可能很重要。 但是,在程序运行之前,不要试图改变你的声明。 摆脱未定义的行为,以便顺序无关紧要。

解决方案:首先不要犯错误。 (当然,说起来容易做起来难得多。)

命名约定可能会有所帮助。 如果你已经调用了你的char变量c ,而你的int变量i ,而不是反之亦然,那么跟踪哪个变量就更容易了。

但是c是用于保存输入字符值的int变量的合理名称 – 不是对于scanf ,而是对于getchar() ,如:

 int c; while ((c = getchar()) != EOF) { /* ... */ } 

该函数需要一系列引用作为附加参数,每个参数指向由格式字符串中相应的%-tag指定的类型的对象,顺序相同。 阅读scanf

这些还可以帮助您:

我不明白为什么我不能在c中获得三个输入

scanf()将新行char留在缓冲区中?

关于问题的最后部分, int的位数总是多于char ,因此不会导致问题。