为什么没有对CPU's状态寄存器在C和C++设计中的应用
Why was no intrinsic access to the CPU's status register in the design of both C and C++?
在溢出标志的情况下,访问该标志对跨体系结构编程来说似乎是一大福音。它将提供一个安全的替代方案,而不是依赖未定义的行为来检查有符号整数溢出,例如:
if(a < a + 100) //detect overflow
我知道有一些安全的替代品,比如:
if(a > (INT_MAX - 100)) //detected overflow
然而,C和C++语言似乎都缺少对状态寄存器或其中单个标志的访问。为什么没有包含此功能,或者做出了哪些语言设计决定禁止包含此功能?
因为C和C++被设计为独立于平台。状态寄存器不是。
如今,二的补码被普遍用于实现有符号整数运算,但情况并非总是如此。一个人的补码或符号和绝对值过去很常见。当C第一次被设计出来的时候,这种CPU仍然被广泛使用。例如,COBOL区分了在那些体系结构上存在的负0和正0。显然,这些体系结构上的溢出行为是完全不同的!
顺便说一句,不能依赖未定义的行为来检测溢出,因为合理的编译器在看到时
if(a < a + 100)
将编写警告并编译
if(true)
(前提是启用了优化并且未关闭特定优化)。
请注意,你不能依赖警告。编译器只会在条件经过等效转换后以true
或false
结束时发出警告,但在许多情况下,条件会在存在溢出的情况下进行修改,而不会以普通true
/false
结束。
- 因为C++被设计成一种可移植的语言,即在许多CPU上编译的语言(例如x86、ARM、LSI-11/2,以及Game Boys、手机、冰箱、飞机、人类操纵芯片和激光剑等设备)。
- 不同CPU的可用标志可能有很大差异
- 即使在同一CPU中,标志也可能不同(采用x86标量与矢量指令)
- 有些CPU可能根本没有您想要的标志
- 必须回答的问题是:当编译器根本无法确定是否使用该标志时,它是否应该始终传递/启用该标志,这不符合只为你使用的东西付费不成文但神圣的C和C定律++
- 因为编译器必须被禁止优化和重新排序代码以保持这些标志的有效性
后者的示例:
int x = 7;
x += z;
int y = 2;
y += z;
优化器可以将其转换为伪汇编代码:
alloc_stack_frame 2*sizeof(int)
load_int 7, $0
load_int 2, $1
add z, $0
add z, $1
这反过来将更类似于
int x = 7;
int y = 2;
x += z;
y += z;
现在,如果您在之间查询寄存器
int x = 7;
x += z;
if (check_overflow($0)) {...}
int y = 2;
y += z;
然后在优化和分解后,可能会以以下结束:
int x = 7;
int y = 2;
x += z;
y += z;
if (check_overflow($0)) {...}
这是不正确的。
可以构造更多的示例,比如发生的常量折叠编译时溢出。
旁注:我记得一个旧的Borland C++编译器有一个小的API来读取当前的CPU寄存器。然而,上面关于优化的论证仍然适用。
另一方面注意:要检查溢出:
// desired expression: int z = x + y
would_overflow = x > MAX-y;
更具体的
auto would_overflow = x > std::numeric_limits<int>::max()-y;
或者更好,更少的混凝土:
auto would_overflow = x > std::numeric_limits<decltype(x+y)>::max()-y;
我能想到以下原因。
-
通过允许访问寄存器标志,语言在平台之间的可移植性受到严重限制。
-
优化器可能会大幅更改表达式,并使您的标志变得无用。
-
这将使语言更加复杂
-
大多数编译器都有一大组内部函数,可以在不使用标志的情况下执行最常见的操作(例如带进位的加法)。
-
大多数表达式都可以用安全的方式重写,以避免溢出。
-
如果你有非常特殊的需求,你总是可以回到内联组装
对状态寄存器的访问似乎还不够,无法进行标准化工作。
- 试图在visual studio上用C++创建一个桌面应用程序
- FFmpeg:制作一个应用程序比直接使用ffmepg更好吗
- c++r值引用应用于函数指针
- 在C应用程序中运行C++(带有STL)函数
- 使用VerQueryValue检索应用程序的文件描述
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 使用调试/崩溃报告将应用程序部署到客户端
- C++控制台应用程序阻止退出
- 码头化的C++应用程序是否向后兼容早期的内核版本
- 将应用程序从32位移植到64位时出现问题
- 有没有任务栏API可以立即应用注册表更改
- 如何改变c++应用程序的视觉效果
- WM_CTLCOLORSTATIC从未在WIN32应用程序中触发
- PC中的程序和PHONE中的本机描述应用程序之间的数据连接
- 应用程序崩溃并显示"symbol _ZdlPvm, version Qt_5 not defined in file libQt5Core.so.5 with link time reference"
- 示例外壳应用程序显示的 V8 "segmentation fault (core dumped)"错误
- phytec phyBOARD iMX-6在从闪存而不是SD卡运行qt5 opengles应用程序时表现不佳(FPS减半
- TMap::Emplace() 在应用现有密钥时会覆盖吗?
- 为什么导入Mixed native/CLR lib.dll的本机C++应用程序没有在Mixed lib.dll中的外部变
- 如何从Windows应用程序输出到标准?