C 变量声明的行为如何?
或者这个:C 变量声明的行为如何?,c,variables,memory,variable-assignment,declaration,C,Variables,Memory,Variable Assignment,Declaration,或者这个: int c; int *x; int i; 只有这样:c变量和i变量前面的x指针。 我知道那些最后的声明没有意义,inti代替了chari,并且添加了一个甚至不需要的指针。 但这是偶然发生的,我想知道这是否只是巧合。函数需要一系列引用作为附加参数,每个引用都指向格式字符串中相应的%-标记指定类型的对象,顺序相同。了解 这些功能还可以帮助您: 关于问题的最后一部分,int的位数总是大于char,因此不会引起问题。如果其余代码没有问题,那么声明变量的顺序应该没有任何区别。声明的顺序
int c;
int *x;
int i;
只有这样:c变量和i变量前面的x指针。
我知道那些最后的声明没有意义,inti代替了chari,并且添加了一个甚至不需要的指针。
但这是偶然发生的,我想知道这是否只是巧合。函数需要一系列引用作为附加参数,每个引用都指向格式字符串中相应的%-标记指定类型的对象,顺序相同。了解 这些功能还可以帮助您:
关于问题的最后一部分,
int
的位数总是大于char
,因此不会引起问题。如果其余代码没有问题,那么声明变量的顺序应该没有任何区别。声明的顺序根本不需要与它们在内存中的排列方式有任何关系。即使有,你也可以通过名字来引用变量;只要代码正确,对i
的引用就是对i
的引用,编译器将生成正确访问变量所需的任何代码
现在,如果您这样做:
int *x;
int c;
int i;
那你就做错了<使用%i
格式的code>scanf需要一个char*
参数,该参数指向值将存储到的char
对象。你给它一个int*
而不是char*
。因此,程序的行为是未定义的;语言标准没有说明它将如何表现
那么为什么它看起来工作正常呢?可能发生的情况是scanf
将int
对象i
的地址视为指向char
的指针。它可能会指向表示i
的第一个字节;例如,i
可能是32位,指针将指向这些位中的前8位。(它们可以是高阶位或低阶位,具体取决于系统。)
现在,当您打印i
的值时:
int i;
scanf("%c", &i);
例如,i
的内容是1个字节,由刚刚读入的字符组成,3个字节为垃圾。这3个垃圾字节很可能都是零,但它们可以是任何东西。如果垃圾字节恰好是0,而第一个字节恰好是高阶字节(即,您在一台机器上),那么您可能会得到“正确”的输出
但不要那样做。由于该行为尚未定义,它可以“正确”运行多年,然后在最糟糕的时刻惊人地失败
这里的教训是C倾向于假设你知道你在做什么。有很多构造具有未定义的行为,这意味着它们是无效的,但是编译器和运行时系统都不需要告诉您存在问题。在C语言中,比在大多数其他语言中更重要的是,作为一名程序员,如何正确处理问题取决于你自己。编译器(和其他工具)将告诉您一些错误,但不是全部错误
在存在未定义行为的情况下,声明变量的顺序可能会有所不同。例如,如果您编写的代码读取或写入超过了变量的结尾,那么存储在那里的内容可能会很重要。但是,在程序运行之前,不要尝试对您的声明进行反复修改。去掉未定义的行为,这样顺序就不重要了
解决方法:首先不要犯错误。(当然,说起来容易做起来难。)
命名约定可能会有所帮助。如果您调用了char
变量c
,调用了int
变量i
,而不是相反,那么跟踪哪个是哪个会更容易
但是c
是用于保存输入字符值的int
变量的合理名称,不是用于scanf
,而是用于getchar()
,如下所示:
printf("%d\n", i);
有人能解释一下什么行为吗?您的问题相当不清楚。
%i
应该是什么意思?@Acme它匹配一个“可选有符号整数,其格式与strtol()主题序列的预期格式相同”。因此,您可以传递它0x2A
@Acme:%i
对于有符号整数是%d
的有效替代方法(即使我更喜欢%d
)。@Acme如果我声明i为整数,则不会打印调用scanf之前引入的字符的值,它打印一个大值,这是因为scanf
忽略了空格字符,因此在换行时停止读取。。我认为没有人在读任何东西。使用getchar()
来修复这个问题。OMG,这就是我要说的,谢谢你的回答,非常有帮助。
printf("%d\n", i);
int c;
while ((c = getchar()) != EOF) {
/* ... */
}