为什么在C和C++的设计中没有对CPU状态寄存器的内在访问?

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++语言都缺少对状态寄存器或其中各个标志的访问.为什么不包含此功能或做出哪些语言设计决定禁止包含此功能?

Jan*_*dec 8

因为C和C++被设计为独立于平台.状态寄存器不是.

这些天,两个补码通常用于实现有符号整数运算,但情况并非总是如此.一个人的补充或标志和绝对价值曾经非常普遍.当C首次设计时,这些CPU仍然普遍使用.例如,COBOL区分负面和正面0,这些存在于这些架构中.显然,这些架构上的溢出行为完全不同!

顺便说一下,你不能依赖未定义的行为来检测溢出,因为看到合理的编译器

if(a < a + 100)
Run Code Online (Sandbox Code Playgroud)

会写一个警告并编译

if(true)
Run Code Online (Sandbox Code Playgroud)

...(提供的优化已打开且特定优化未关闭).

请注意,您不能依赖警告.编译器只会在条件结束truefalse等效转换后发出警告,但在很多情况下,条件将在溢出时修改而不会以plain true/ 结尾false.


Seb*_*ach 6

  • 因为C++被设计为一种可移植的语言,即可以在许多CPU上编译的语言(例如x86,ARM,LSI-11/2,以及Game Boys,Mobile Phones,Freezers,Airplanes,Human Manipulation Chips和Laser Swords等设备).
    • CPU之间的可用标志可能大不相同
    • 即使在同一个CPU中,标志也可能不同(采用x86标量与矢量指令)
    • 有些CPU可能根本没有你想要的标志
  • 必须回答的问题是:当编译器无法确定是否完全使用时,编译器是否应始终提供/启用该标志?,这不符合你使用 C和C++的不成文但圣洁的法律所付出的代价
  • 因为必须禁止编译器进行优化,例如重新排序代码以保持这些标志有效

后者的例子:

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)