#include<stdio.h>
#include<conio.h>
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 变量和 x 指针在 i 变量之前。 我知道那些最后的声明没有意义, int i 而不是 char i ,以及一个甚至不需要的添加指针。 但这是偶然发生的,我想知道这是不是巧合。
答案 0 :(得分:1)
该函数需要一系列引用作为附加参数,每个参数指向由格式字符串中相应的%-tag指定的类型的对象,顺序相同。阅读scanf
这些还可以帮助您:
I don't understand why I can't get three inputs in c
scanf() leaves the new line char in buffer?
关于问题的最后部分,int
的位数始终大于char
,因此不会导致问题。
答案 1 :(得分:1)
您声明变量的顺序应该没有任何区别,假设其余代码没有任何问题。声明的顺序不需要与它们在记忆中的布局方式有任何关系。即使它确实如此,也可以通过名称来引用变量;只要您的代码正确,对i
的引用就是对i
的引用,编译器将生成正确访问变量所需的任何代码。
现在,如果你这样做:
int i;
scanf("%c", &i);
那时你做错了什么。 scanf
格式的"%i"
需要char*
参数,该参数指向将存储值的char
对象。你给的是int*
而不是char*
。结果,你的程序的行为是不确定的;语言标准没有说明它将如何表现。
那为什么它似乎正常工作?可能发生的是scanf
将int
对象i
的地址视为指向char
的指针。它可能指向i
表示的第一个字节;例如,i
可能是32位,指针将指向这些位的前8位。 (它们可以是高阶或低阶位,具体取决于系统。)
现在打印i
的值:
printf("%d\n", i);
i
的内容,例如,1个字节,包含您刚读入的任何字符,以及3个字节的垃圾。这3个垃圾字节可能都是零,但它们可以是任何东西。如果垃圾字节恰好是0,并且第一个字节恰好是高位字节(即,你在big-endian机器上),那么你很可能得到“正确”的输出。
但不要这样做。由于行为未定义,它可以“正确”工作多年,然后在最糟糕的时刻失败。
这里的教训是,C倾向于认为你知道自己在做什么。有一个 lot 的构造具有未定义的行为,这意味着它们无效,但是编译器和运行时系统都不需要告诉您存在问题。在C语言中,比大多数其他语言更重要的是,作为一名程序员,你要把事情弄清楚。编译器(和其他工具)会告诉你一些错误,但不是所有错误。
如果存在未定义的行为,您声明变量的顺序可以有所不同。例如,如果您编写的代码读取或写入变量的末尾,那么存储在那里的情况就很重要了。但是,在程序运行之前,不要试图改变你的声明。摆脱未定义的行为,因此订单不重要。
解决方案:首先不要犯错误。 (当然,说起来容易做起来容易得多。)
命名约定可能会有所帮助。如果您调用了char
变量c
和int
变量i
,而不是反之亦然,那么跟踪哪个变量就更容易了。< / p>
但c
是用于保存输入字符值的int
变量的合理名称 - 不是scanf
,而是getchar()
,如:
int c;
while ((c = getchar()) != EOF) {
/* ... */
}