Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 变量声明的行为如何?_C_Variables_Memory_Variable Assignment_Declaration - Fatal编程技术网

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) {
    /* ... */
}