在C中,将变量初始化为它自己的值是否有意义?如果是,那该怎么办?
请允许我详细说明。在Git源代码中,有一些例子可以将变量初始化为它自己的未定义值,如transport.c或wt-status.c中所示。我从那些声明中删除了作业并运行了测试。看到没有回归,我认为这些任务是多余的。
另一方面,我使用GCC 4.6和Clang 2.9进行了一些简单的测试。
#include <stdio.h>
int main() {
printf("print to increase probability of registers being non-zero\n");
int status = status;
return printf("%i\n", status);
}
使用-Wall -std=c99
和各种-O
级别进行编译不会显示任何警告并显示status == 0
。具有非零优化级别的Clang会打印一些垃圾值。这让我推断出这些表达式的结果是不确定的。
我可以想象这样的赋值可以抑制未初始化的变量警告,但是从Git中获取的示例并非如此。删除分配不会引入任何警告。
此类作业是否为未定义的行为?如果没有,你用它做什么?
我建议在Git邮件列表上进行更改。 Here's what I've learned
答案 0 :(得分:11)
这是编译,因为标准C99§6.2.1/ 7 说:
任何不是结构,联合或枚举标记的标识符“都具有在其声明符完成后才开始的范围。”声明符之后是初始化器。
但是,status
的值为不确定。而且你不能依赖它被初始化为有意义的东西。
它是如何运作的?
int status
为堆栈(本地存储)上存在的变量创建一个空间,然后进一步读取以执行status = status
,status
可能会被初始化为堆栈中存在的任何值帧。
你怎么能防止这种自我初始化?
gcc提供了一个特定的设置来检测自我初始化并将它们报告为错误:
-Werror = uninitialized -Winit-self
为什么在此代码中使用它?
我认为在上述代码中使用的唯一原因是为ex:在transport.c
中抑制未使用的变量警告,如果控件永远不在while
循环内,那么在该控制流中{ {1}}将不使用,编译器必须为其生成警告。同样的情况似乎与cmp
status
变量一致
答案 1 :(得分:1)
对我来说,这种自我分配初始化的唯一原因是避免警告。
对于transport.c
,我甚至不理解为什么它有用。我会让cmp
未初始化。
我自己的习惯(至少在C中)是初始化所有变量,通常为0.编译器将优化不需要的初始化,并且初始化所有变量使调试更容易。
有一种情况,我希望变量保持未初始化状态,我可以自行分配:随机种子:
unsigned myseed = myseed;
srand(myseed);
答案 2 :(得分:1)
在MacOS X 10.7.2上,我尝试了这个例子 - 结果显示......
$ cat x3.c
#include <stdio.h>
int status = -7;
int main()
{
printf("status = %d\n", status);
int status = status;
printf("status = %d\n", status);
return 0;
}
$ make x3
gcc -O -std=c99 -Wall -Wextra x3.c -o x3
$ ./x3
status = -7
status = 1787486824
$
status
已使用main()
中的本地printf()
的堆栈空间,因此自我初始化会复制垃圾。
答案 3 :(得分:0)
我认为status = status
不会更改status
的值(与int status;
相比)。我认为它用于抑制unused variable
警告。