考虑以下示例:
int a[4];
int main() {
a[4] = 12; // <--
return 0;
}
这显然是一个出界错误,不是吗?我想知道gcc什么时候会对此发出警告,并发现只有在优化为-O2
或更高时它才会这样做(这受-ftree-vrp
选项的影响,该选项仅为{{1}自动设置} 或更高)。
我真的不明白为什么这是有道理的,否则gcc不会发出警告是否正确。
文档说明了这个问题:
这允许优化器删除不必要的范围检查,如数组绑定检查和空指针检查。
不过,我不明白为什么不需要检查?
答案 0 :(得分:1)
您的示例是常量传播的情况,而不是值范围传播,它肯定会在我的gcc版本(4.5.1)上触发警告,无论是否-ftree-vrp
已启用。
通常,Java和Fortran是gcc支持的唯一语言(默认情况下为Java,如果您明确要求使用-fbounds-check
,则为Fortan)将生成用于检查数组边界的代码。
但是,虽然C / C ++不支持任何此类事情,但如果编译器认为某些内容不对,编译器仍会在编译时警告。对于常数,这是非常明显的,对于可变范围,它有点难度。
子句“允许编译器删除不必要的范围检查”涉及例如使用无符号8位宽变量索引到具有> 256个条目的数组或无符号16位值以索引到数组> 65536个元素。或者,如果你在一个循环中迭代一个数组,并且(变量)循环计数器是 bounded 的值可以被证明为合法数组索引的编译时常量,所以计数器永远不会可能超出阵列界限 在这种情况下,编译器既不警告您也不为支持此目标语言生成任何代码。