Tim*_*are 6 c c++ language-design
在溢出标志的情况下,似乎访问此标志将是跨架构编程的一大福音.它将提供一种安全的替代方法来依赖未定义的行为来检查有符号整数溢出,例如:
if(a < a + 100) //detect overflow
Run Code Online (Sandbox Code Playgroud)
我确实知道有安全的替代方案,例如:
if(a > (INT_MAX - 100)) //detected overflow
Run Code Online (Sandbox Code Playgroud)
但是,似乎C和C++语言都缺少对状态寄存器或其中各个标志的访问.为什么不包含此功能或做出哪些语言设计决定禁止包含此功能?
因为C和C++被设计为独立于平台.状态寄存器不是.
这些天,两个补码通常用于实现有符号整数运算,但情况并非总是如此.一个人的补充或标志和绝对价值曾经非常普遍.当C首次设计时,这些CPU仍然普遍使用.例如,COBOL区分负面和正面0,这些存在于这些架构中.显然,这些架构上的溢出行为完全不同!
顺便说一下,你不能依赖未定义的行为来检测溢出,因为看到合理的编译器
if(a < a + 100)
Run Code Online (Sandbox Code Playgroud)
会写一个警告并编译
if(true)
Run Code Online (Sandbox Code Playgroud)
...(提供的优化已打开且特定优化未关闭).
请注意,您不能依赖警告.编译器只会在条件结束true或false等效转换后发出警告,但在很多情况下,条件将在溢出时修改而不会以plain true/ 结尾false.
后者的例子:
int x = 7;
x += z;
int y = 2;
y += z;
Run Code Online (Sandbox Code Playgroud)
优化器可以将其转换为该伪汇编代码:
alloc_stack_frame 2*sizeof(int)
load_int 7, $0
load_int 2, $1
add z, $0
add z, $1
Run Code Online (Sandbox Code Playgroud)
反过来会更相似
int x = 7;
int y = 2;
x += z;
y += z;
Run Code Online (Sandbox Code Playgroud)
现在,如果您在中间查询寄存器
int x = 7;
x += z;
if (check_overflow($0)) {...}
int y = 2;
y += z;
Run Code Online (Sandbox Code Playgroud)
然后在优化和消散之后你可能会以此结束:
int x = 7;
int y = 2;
x += z;
y += z;
if (check_overflow($0)) {...}
Run Code Online (Sandbox Code Playgroud)
这是不正确的.
可以构造更多示例,就像常量折叠编译时溢出所发生的那样.
旁注:我记得一个旧的Borland C++编译器,它有一个小API来读取当前的CPU寄存器.但是,上面关于优化的论证仍然适用.
另一方面:检查溢出:
// desired expression: int z = x + y
would_overflow = x > MAX-y;
Run Code Online (Sandbox Code Playgroud)
更具体
auto would_overflow = x > std::numeric_limits<int>::max()-y;
Run Code Online (Sandbox Code Playgroud)
或者更好,更少具体:
auto would_overflow = x > std::numeric_limits<decltype(x+y)>::max()-y;
Run Code Online (Sandbox Code Playgroud)