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

2 c++ visual-c++

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

int array[100];
array[-50] = 100; // Crash!!
Run Code Online (Sandbox Code Playgroud)

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

那为什么要编译呢?

Spo*_*ook 7

array[-50] = 100;
Run Code Online (Sandbox Code Playgroud)

实际意味着:

*(array - 50) = 100;
Run Code Online (Sandbox Code Playgroud)

考虑这段代码:

int array[100];
int *b = &(a[50]);
b[-20] = 5;
Run Code Online (Sandbox Code Playgroud)

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

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


Jon*_*Jon 6

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

*(&array[0] + (-50))
Run Code Online (Sandbox Code Playgroud)

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

现在肯定是因为这里-50 一个编译时常量,并且由于访问数组的减去50的元素几乎总是一个错误,编译器可能(也许应该)为此产生警告.

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

与像其他结构对比这个if (answer = 42)不要指望在实际的代码,看看(如果仅仅是因为它是如此容易做出错误),哪些是难以调试(眼睛可以轻松读取===,而这-50马上伸出).在这些情况下,编译器警告会更有效率.