在处理数组访问时可能会生成不一致的代码
Possibly non-conformant code generation when dealing with array accesses
对于以下简单的代表代码
int foo()
{
extern int i;
extern int a[];
int sum = 0;
sum += a[i + 10];
sum += a[i + 20];
return sum;
}
LLVM生成的代码看起来像
movl a+40(,%eax,4), %eax
...
movl a+80(,%eax,4), %eax
这个代码真的符合C/C++标准吗?
在给定C/C++的情况下,生成的代码不应该计算a + (40 + eax * 4)
而不是(a + 40) + (eax * 4)
吗?仅当计算的地址位于同一数组对象中时,才定义地址算术?
在上面的情况下,可能会发生a + 40
落在数组之外,但a + (40 + eax * 4)
仍然可以在同一个数组中(如果"i"为负值)。
C++标准定义了C++程序的行为。编译器可以选择任何方式来实现这种行为。
指针只能指向单个数组的限制只存在于C++代码中;它可能适用于编译器将C++翻译成的语言,也可能不适用,但即使适用,这种限制也是由新的(通常是汇编)语言定义的,而不是由C++定义的。
汇编代码没有C/C++标准,所以您提出的问题是不连贯的。就C/C++标准而言,唯一重要的是,如果C/C++源代码严格符合这些标准,那么汇编代码是否会产生标准所要求的行为。如果你相信它不会,你还没有解释为什么你相信它。
只有当计算出的地址落在同一数组对象中时,C/C++才定义地址算术?
这是真的。这意味着如果访问超出a[]
的范围,则行为是未定义的。
我不知道你是如何从中得出"代码不一致"的结论的。如果证明a
是正确的大小,使得a[i+10]
和a[i+20]
不超出a
的范围,则代码符合,否则它不会
如果这些超出了a
的范围,那么行为是未定义的,这意味着在这种情况下,您不能抱怨编译器发出的任何代码。
在上面的情况下,可能会发生+40落在数组之外,但+(40+eax*4)仍然可以在同一数组中(如果"i"为负值)。
没关系,行为是不明确的。
正如其他人所说,标准中没有任何内容确切说明编译器应该做什么,只要它能产生正确的结果。
在您的情况下,它通过将a+40
转换为常数值来优化计算(一旦代码转换为机器代码,它将是一个常数),而不是使用更长形式的指令,或者更糟的是,使用第二个寄存器来添加常数40。如果i
为负,则将从地址中减去。无论您将其计算为(a+40) + -5*4
还是a + (40 + -5*4)
,都不会有任何区别。
请注意,如果您使用64位模式,编译器将首先生成代码对索引进行签名扩展,例如:
movl i(%rip), %eax
leal 10(%rax), %ecx
addl $20, %eax
movslq %eax, %rdx
movslq %ecx, %rcx
movl a(,%rcx,4), %eax
addl a(,%rdx,4), %eax
ret
如果我们将i
更改为unsigned
:
movl i(%rip), %eax
leal 20(%rax), %edx
leal 10(%rax), %ecx
movl a(,%rcx,4), %eax
addl a(,%rdx,4), %eax
ret
请注意额外的movslq
指令,该符号将32位int
值扩展为64位值。
(我无法生成与您在示例中显示的完全相同的指令集,但我没有尝试所有选项的组合,您也没有说明您正在使用哪个版本的clang-我只是猜测您正在使用32位模式,因为这似乎比64位结果更符合我的结果。如果您发布的代码来自64位编译器,那么几乎可以肯定这是一个错误)
- 大于65535的C++数组[size]引发不一致的溢出
- 在 C++(和 C)中进行类型转换时明显不一致
- 填充上编译器生成的复制构造函数之间的不一致
- 犰狳的 print() 方法和 cout 在从 Rcpp 调用时顺序不一致
- CreateDIBSection为同一图像返回不一致的位图位值
- 在 Qml 中从 QSqlTableModel 中删除单行时视图不一致
- 模板参数推导不一致
- "std::forward"和"std::move"真的不生成代码吗?
- bash脚本在使用popen()时不返回代码以调用C ++程序
- 声明中不一致的no是否违反ODR?
- 如何删除分支因子不一致的树,最大为 30,40
- 为什么向量不在代码块中运行?
- 从 C++ 函数与 Python 函数返回的不一致值用于偏斜正态分布
- 从 C 字符串构造 std::string 与从另一个 std::string 构造 std::string 不一致
- 如何查找导致结果不一致的代码
- C++ - 为什么我的cout代码显示小数不一致
- 代码::封锁前构建选项与命令行(QT)不一致
- IO文件代码不一致
- 在处理数组访问时可能会生成不一致的代码
- 收到错误:将我的 c++ 代码从 Linux 移植到 android 时'asm'中的操作数约束不一致