将变量初始化为其自己的未定义值

时间:2011-11-27 07:51:46

标签: c

在C中,将变量初始化为它自己的值是否有意义?如果是,那该怎么办?

请允许我详细说明。在Git源代码中,有一些例子可以将变量初始化为它自己的未定义值,如transport.cwt-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

4 个答案:

答案 0 :(得分:11)

这是编译,因为标准C99§6.2.1/ 7 说:

  

任何不是结构,联合或枚举标记的标识符“都具有在其声明符完成后才开始的范围。”声明符之后是初始化器。

但是,status的值为不确定。而且你不能依赖它被初始化为有意义的东西。

它是如何运作的?
int status为堆栈(本地存储)上存在的变量创建一个空间,然后进一步读取以执行status = statusstatus可能会被初始化为堆栈中存在的任何值帧。

你怎么能防止这种自我初始化?
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警告。