变量声明的行为如何?
#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);
}
程序将以相同的方式使用下一个变量声明而不是上面的变量声明:
this:
int c;
int *x;
int i;
或 this:
int *x;
int c;
int i;
并且只有这样:c 变量和 x 指针在 i 变量之前。 我知道最后的声明没有意义,用 int i 而不是 char i,并且添加了一个甚至不需要的指针。 但这是偶然发生的,我想知道这是否只是巧合。
#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);
}
The program will behave in the same way with the next variable declarations instead of the above variable declaration:
this:
int c;
int *x;
int i;
or this:
int *x;
int c;
int i;
And only this way: c variable and a x pointer before the i variable.
I know that those last declarations haven't sense, the int i instead of char i, and an added pointer that isn't even needed.
But this have been occurred accidentally and im wondering if it's only an a coincidence.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
假设代码的其余部分没有任何问题,声明变量的顺序应该没有任何区别。声明的顺序不需要与它们在内存中的布局方式有任何关系。即使确实如此,您也可以通过名称来引用变量;只要您的代码正确,对
i
的引用就是对i
的引用,编译器将生成正确访问该变量所需的任何代码。现在,如果你这样做:
那么你就做错了。具有
"%i"
格式的scanf
需要一个char*
参数,该参数指向要写入的char
对象该值将被存储。您给它的是int*
而不是char*
。因此,你的程序的行为是未定义的;语言标准没有说明它的行为方式。那么为什么它看起来工作正常呢?可能发生的情况是
scanf
将int
对象i
的地址视为指向char
的指针>。它可能会指向i
表示的第一个字节;例如,i
可能是 32 位,指针将指向这些位的前 8 位。 (它们可能是高位或低位,具体取决于系统。)现在,当您打印
i
的值时:i
的内容是,例如,1 个字节由您刚刚读入的任何字符组成,3 个字节是垃圾。这 3 个垃圾字节很可能全部为零,但它们可以是任何东西。如果垃圾字节恰好为 0,并且第一个字节恰好是高位字节(即,您位于 big-endian 机器),那么您可能会得到“正确”的输出。但不要这样做。由于行为是未定义的,它可以“正确”工作多年,然后在最糟糕的时刻彻底失败。
这里的教训是,C 倾向于假设你知道自己在做什么。有很多构造具有未定义的行为,这意味着它们无效,但编译器和运行时系统都不需要告诉您存在问题。与大多数其他语言相比,C 语言更需要程序员将事情做好。编译器(和其他工具)会告诉您一些错误,但不是全部。
在存在未定义行为的情况下,声明变量的顺序可能会产生影响。例如,如果您编写的代码读取或写入超过变量的末尾,那么那里存储的内容可能很重要。但是,在程序运行之前,不要试图随意更改声明。摆脱未定义的行为,因此顺序并不重要。
解决方案:首先不要犯错误。 (当然,说起来容易做起来难。)
命名约定会很有帮助。如果您将
char
变量称为c
,并将int
变量称为i
,而不是反之亦然,那么它会更容易跟踪哪个是哪个。但是,对于用于保存输入字符值的 int 变量来说,
c
是一个合理的名称——不是用于scanf
,而是用于getchar( )
,如:The order in which you declare your variables should make no difference at all, assuming there's nothing wrong with the rest of your code. The order of declaration needn't have anything at all to do with the way they're laid out in memory. And even if it did, you refer to variables by name; as long as your code is correct, a reference to
i
is a reference toi
, and the compiler will generate whatever code is needed to access the variable correctly.Now if you do this:
then you're doing something wrong.
scanf
with a"%i"
format requires achar*
argument, which points to thechar
object into which the value will be stored. You're giving it anint*
rather than achar*
. As a result, your program's behavior is undefined; the language standard says nothing about how it will behave.So why does it appear to work correctly? What's probably happening is that
scanf
treats the address of theint
objecti
as if it were a pointer to achar
. It will probably point to the first byte of the representation ofi
; for example,i
might be 32 bits, and the pointer will point to the first 8 of those bits. (They could be the high-order or low-order bits, depending on the system.)Now when you print the value of
i
:the contents of
i
are, for example, 1 byte consisting of whatever character you just read into it, and 3 bytes of garbage. Those 3 garbage bytes may well all be zeros, but they could be anything. If the garbage bytes happen to be 0, and the first byte happens to be the high-order byte (i.e., you're on a big-endian machine), then you're likely to get the "correct" output.But don't do that. Since the behavior is undefined, it can work "correctly" for years, and then fail spectacularly at the worst possible moment.
The lesson here is that C tends to assume that you know what you're doing. There are a lot of constructs that have undefined behavior, which means that they're invalid, but neither the compiler nor the runtime system is required to tell you that there's a problem. In C, more than in most other languages, it's up to you as a programmer to get things right. The compiler (and other tools) will tell you about some errors, but not all of them.
And in the presence of undefined behavior, the order in which you declare your variables can make a difference. For example, if you write code that reads or writes past the end of a variable, it can matter what happens to be stored there. But don't be tempted to shuffle your declarations around until the program works. Get rid of the undefined behavior so the order doesn't matter.
The solution: Don't make mistakes in the first place. (Of course that's much easier said than done.)
And naming conventions can be helpful. If you had called your
char
variablec
, and yourint
variablei
, rather than vice versa, it would have been easier to keep track of which is which.But
c
is a reasonable name for anint
variable used to hold input character values -- not forscanf
, but forgetchar()
, as in:该函数需要一系列引用作为附加参数,每个引用都以相同的顺序指向由格式字符串中相应的 % 标记指定的类型的对象。了解scanf
这些还可以帮助您:
我不明白为什么我无法获得三个输入c
scanf() 留下新行char in buffer?
关于你问题的最后部分,
int
的位数总是多于char
,所以它不会导致 问题。The function expects a sequence of references as additional arguments, each one pointing to an object of the type specified by their corresponding %-tag within the format string, in the same order. Read about scanf
These can additionally help you:
I don't understand why I can't get three inputs in c
scanf() leaves the new line char in buffer?
Regarding the last portion of your question, the number of bits of
int
is always more thanchar
, so it won't cause a problem.