编译:
#include <iostream>
int main()
{
for (int i = 0; i < 4; ++i)
std::cout << i*1000000000 << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
并gcc
产生以下警告:
warning: iteration 3u invokes undefined behavior [-Waggressive-loop-optimizations]
std::cout << i*1000000000 << std::endl;
^
Run Code Online (Sandbox Code Playgroud)
我知道有一个有符号的整数溢出.
我不能得到的是为什么i
价值被溢出操作打破了?
我已经阅读了为什么x86上的整数溢出与GCC导致无限循环的答案?,但我仍然不清楚为什么会发生这种情况 - 我认为"未定义"意味着"任何事情都可能发生",但这种特定行为的根本原因是什么?
编译: gcc (4.8)
(参考这个问题和答案.)
在C++ 17标准之前,[basic.compound]/3中包含以下句子:
如果类型T的对象位于地址A,则类型为cv T*的指针(其值为地址A)被称为指向该对象,而不管该值是如何获得的.
但是自从C++ 17以来,这句话已被删除.
例如,我相信这句话使这个示例代码定义,并且从C++ 17开始这是未定义的行为:
alignas(int) unsigned char buffer[2*sizeof(int)];
auto p1=new(buffer) int{};
auto p2=new(p1+1) int{};
*(p1+1)=10;
Run Code Online (Sandbox Code Playgroud)
在C++ 17之前,p1+1
保持地址*p2
并具有正确的类型,因此*(p1+1)
是指向*p2
.在C++中,17 p1+1
是一个指向前端的指针,所以它不是指向对象的指针,我相信它不是可以解除引用的.
对标准权的这种修改的解释是否还有其他规则来补偿所引用的句子的删除?
因此,标准(参考N1570)说明了以下关于比较指针的内容:
C99 6.5.8/5关系运算符
比较两个指针时,结果取决于指向的对象的地址空间中的相对位置.... [在聚合中剪切明显的比较定义] ... 在所有其他情况下,行为未定义.
这个UB实例的基本原理是什么,而不是指定(例如)转换intptr_t
和比较它?
是否存在一些机器架构,其中指针的合理总排序难以构建?是否存在一些优化或分析,不受限制的指针比较会阻碍?
这个问题的删除答案提到这条UB允许跳过段寄存器的比较并且仅比较偏移.保存特别有价值吗?
(同样删除的答案,以及此处的答案,请注意,在C++中,std::less
需要对指针实现总顺序,无论正常比较运算符是否执行.)