为什么这段代码在没有警告的情况下编译
Why does this code compile without warnings?
我不知道为什么这段代码符合:
int array[100];
array[-50] = 100; // Crash!!
。编译器仍然可以正确编译,没有编译错误和警告。
那么它为什么要编译呢?
array[-50] = 100;
实际上在这里意味着:
*(array - 50) = 100;
请考虑以下代码:
int array[100];
int *b = &(a[50]);
b[-20] = 5;
此代码有效,不会崩溃。编译器无法知道代码是否会崩溃以及程序员想对数组做什么。所以它不抱怨。
最后,请注意,在查找代码中的错误时不应依赖编译器警告。编译器不会找到你的大部分错误,他们几乎不会尝试为你提供一些提示来简化错误修复过程(有时他们甚至可能被误解并指出,有效的代码是错误的(。此外,该标准实际上从不要求编译器发出警告,因此这些只是编译器实现者的善意行为。
它编译是因为表达式array[-50]
被转换为等效的
*(&array[0] + (-50))
这是另一种说法"将内存地址&array[0]
并sizeof(array[0])
-50 倍添加到其中,然后将生成的内存地址的内容及其后面的内容解释为int
",按照通常的指针算术规则。这是一个完全有效的表达式,其中-50
可能真的是任何整数(当然它不需要是编译时常量(。
现在肯定是真的,因为这里的-50
是一个编译时常量,并且由于访问数组的第 50 个元素几乎总是一个错误,编译器可以(也许应该(为此生成警告。
但是,我们还应该考虑到,检测此特定条件(静态索引到具有明显无效索引的数组(是您不希望在实际代码中看到的。因此,编译器团队的资源可能会更好地用于其他事情。
将其与其他结构(如if (answer = 42)
(进行对比,这些结构确实希望在实际代码中看到(如果只是因为很容易打错字(并且难以调试(眼睛可以轻松地将=
读取为==
,而该-50
立即突出(。在这些情况下,编译器警告的效率要高得多。
编译器不需要在编译时捕获所有潜在问题。C 标准允许在运行时出现未定义的行为(这是执行此程序时发生的情况(。您可以将其视为不捕获此类错误的法律借口。
不过,有一些编译器和静态程序分析器可以捕获像这样的琐碎错误。
真正的编译器可以(注意:需要将编译器切换到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.
如果您有较小的 (*( 编译器,则可能需要手动设置警告。
(*( 即,不太用户友好
内的数字只是一个索引。 它告诉您在内存中执行多少步才能找到您请求的号码。 array[2]
表示从数组的开头开始,向前跳两次。
你刚刚告诉它向后跳50次,这是一个有效的说法。 但是,我无法想象这样做有充分的理由......
- 关于std::move的使用,是否有编译警告
- 示例C++项目编译中的警告
- Steam 回调在 Linux / GCC 编译期间触发警告
- C++警告:编译指示在主文件中一次
- 如何在类成员函数中获得类似printf中的编译警告
- 编译按位 OR 时出现警告 C4805
- C++编译新的警告过滤器
- GCC 编译时出现警告:未知转义序列:"\040"
- 使用预编译的标题接近时,大量的QT警告
- 编译时收到未初始化的内存警告
- 警告:不能解析.gnu_debugdata部分;LZMA支持在编译时被禁用
- 编译错误:(警告:控制到达非空函数 [-wreturn 类型] 的末尾)
- clang:警告:编译期间未使用的参数:"-stdlib=libc++"
- 如何修复未知编译指示 gcc 警告
- 有没有办法自定义编译错误/警告消息
- 窄转换编译警告.如何解决它
- C++就地析构函数编译警告
- 如何在 ubuntu 12.10 中隐藏 g++ c++11 编译警告
- 在Ubuntu中使用OpenCV进行编译警告
- 警告:编译到.so时找不到入口符号start-