为什么这段代码编译时没有警告?

时间:2013-02-12 13:10:15

标签: c++ visual-c++

我不知道为什么这段代码符合:

int array[100];
array[-50] = 100; // Crash!!

...编译器仍可正常编译,无需编译错误和警告。

那为什么要编译呢?

5 个答案:

答案 0 :(得分:7)

array[-50] = 100;

实际上意味着:

*(array - 50) = 100;

考虑这段代码:

int array[100];
int *b = &(a[50]);
b[-20] = 5;

此代码有效且不会崩溃。编译器无法知道代码是否会崩溃以及程序员想要对数组做什么。所以它没有抱怨。

最后,请注意,在查找代码中的错误时,不应该依赖编译器警告。编译器不会找到你的大部分错误,他们几乎没有尝试为你提供一些提示来缓解错误修正过程(有时他们甚至可能会弄错并指出,有效的代码是错误的)。此外,标准实际上从不要求编译器发出警告,因此这些只是编译器实现者的良好意愿。

答案 1 :(得分:6)

它编译是因为表达式array[-50]被转换为等价的

*(&array[0] + (-50))

这是另一种说法“取内存地址&array[0]并添加-50倍sizeof(array[0]),然后解释生成的内存地址的内容及其后面的内容{{1按照通常的指针算术规则。这是一个完全有效的表达式,其中int可能真的是任何整数(当然它不需要是编译时常量)。

现在肯定是因为-50 编译时常量,并且因为访问数组的第50个元素几乎总是错误,所以编译器可以(和也许应该)为此发出警告。

但是,我们还应该考虑检测这种特定条件(静态索引到具有明显无效索引的数组)是您不希望在实际代码中看到的内容。因此,编译器团队的资源可能会更好地用于其他事情。

将此与其他 希望在实际代码中看到的-50构造进行对比(如果只是因为它很容易犯这个错误)并且很难调试( eye可以轻松地将if (answer = 42)视为=,而==可以立即显示出来。在这些情况下,编译器警告会更有效率。

答案 2 :(得分:2)

True compilers do(注意:需要将编译器切换到clang 3.2,gcc不是用户友好的)

Compilation finished with warnings:
source.cpp:3:4: warning: array index -50 is before the beginning of the array [-Warray-bounds]
array[-50] = 100;
^ ~~~
source.cpp:2:4: note: array 'array' declared here
int array[100];
^
1 warning generated.

如果你有一个较小的(*)编译器,你可能需要手动设置警告。

(*)即用户友好性

答案 3 :(得分:1)

编译器不需要在编译时捕获所有潜在的问题。 C标准允许在运行时出现未定义的行为(执行此程序时会发生这种情况)。您可以将其视为不捕获此类错误的合法借口。

虽然有编译器和静态程序分析器可以捕获这样的琐碎错误。

答案 4 :(得分:0)

括号内的数字只是一个索引。它告诉您内存中要查找您要求的号码的步数。 array[2]表示从数组的开头开始,然后向前跳两次。

你刚刚告诉它向后跳50次,这是一个有效的陈述。但是,我无法想象有这么好的理由......