2011-03-27 98 views
19
#include <iostream> 

int main(int argc, char** args) { 
    int foo = foo + 4; 
    std::cout << foo << std::endl; 
} 

而后续问题,是否有编译器标志来阻止这种事情?我发现 - 有时候墙有效,更好的办法是完全防止它。这是什么意思? int foo = foo + 4;

My compiler: 
g++ -v 
Using built-in specs. 
Target: i486-linux-gnu 
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.3-4ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-plugin --enable-objc-gc --enable-targets=all --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu 
Thread model: posix 
gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) 
+1

一个编译器标志停止什么样的事情? – tkerwin 2011-03-27 16:46:13

+1

你的问题到底是什么?你为什么不初始化foo? – mbx 2011-03-27 16:46:32

+0

'int foo = foo + 4;'并不意味着什么。你写的时候是什么意思? – 2011-03-27 16:46:54

回答

30

不,没有保证的办法来阻止这类事情。它是C++和C的组成部分,变量的名称在其初始化程序中可见。它允许你做这样的事情

T *t = malloc(sizeof(*t)); 

有列出需要在简单的情况下诊断的C++问题一个问题的报告,但目前的编译器不需要诊断你的情况。

这也是有效的in a different context

编辑:澄清 - 您的代码段的行为未定义:您正在读取未初始化变量的值。这些编译器不需要诊断,并不意味着行为被定义。

+0

这是有道理的。我必须等待8分钟才能接受.... – Eric 2011-03-27 16:50:23

+3

+1,总是从litb学习新东西! – Xeo 2011-03-27 16:51:46

3

我敢打赌,这意味着未定义的行为。

编辑:请参阅answer to another question的引文。

编辑:最有可能的是,RHS中的值取自堆栈中未初始化的内存位置,将4添加到堆栈中,并将结果用于初始化。

+0

@downvoter:谨慎解释? – Vlad 2011-03-27 16:48:52

+0

@Nawaz:这并没有说出答案中的错误。顺便说一句,我提供的链接引用证明答案是正确的。 – Vlad 2011-03-27 16:53:11

+0

@Vlad:嗯..你说得对。我试图撤销我的downvote,但为此你必须编辑你的帖子,因为它不会让我撤消! – Nawaz 2011-03-27 16:58:09

6
int foo = foo + 4; 

这是未定义的行为。一些编译器归零自动的空间为本地变量时,其他人可能不会,所以富可能包含堆的垃圾

+0

@downvoter:解释你的downvote – BlackBear 2011-03-27 16:49:41

+0

@Nawaz:@ Johannes的回答说对了这个:未定义的行为 – BlackBear 2011-03-27 16:55:21

+0

@BlackBear:嗯..你是对的。我试图撤销我的downvote,但为此你必须编辑你的帖子,因为它不会让我撤消! – Nawaz 2011-03-27 16:58:27

0

我希望任何中途像样的编译器发出的INT FOO警告= FOO + 4;其默认配置为。好的人可以选择完全拒绝它作为“使用未初始化的变量”和/或接受任何特定的发生,在程序员明确知道发生了什么并且不关心意外行为的情况下。

我例如经常用来写INT拨动=切换^ 1回来时,编译器不那么挑剔,如果所有我想要的是一个拨动开关,我并不在乎它是否启动TRUE或天假。现在我可能会写static bool toggle = TRUE;切换= ^切换

2

要想从海湾合作委员会的警告对于这个特殊的代码,你需要-Wuninitialized-Wall包括本)-O(或以上0任何优化级)。

原因是gcc无法诊断未初始化变量的使用,除非它进行数据流分析,并且在优化禁用时不会执行数据流分析。优化在默认情况下被禁用。