Vil*_*ray 12 c casting c99 type-conversion language-lawyer
在C99标准的第7.18.1.1节第1段中:
typedef名称
intN_t指定有符号整数类型,其宽度为N,无填充位和二进制补码表示.
根据C99标准,精确宽度有符号整数类型需要具有二进制补码表示.这意味着,例如,int8_t具有最小值-128而不是1的补码最小值-127.
第6.2.6.2节第2段允许实现决定是将符号位解释为符号和幅度,二进制补码还是一个补码:
如果符号位为1,则应以下列方式之一修改该值:
- 符号位0的相应值被否定(符号和幅度);
- 符号位的值为 - (2 N)(二进制补码);
- 符号位的值为 - (2 N - 1)(1'补码).
方法之间的不同之处很重要,因为二进制补码(-128)中的整数的最小值可能超出了补码(-127to 127)中可表示的值的范围.
假设一个实现将int类型定义为具有ones' complement表示,而int16_t类型具有two's complementC99标准保证的表示.
int16_t foo = -32768;
int bar = foo;
Run Code Online (Sandbox Code Playgroud)
在这种情况下,转换int16_t是否int会导致实现定义的行为,因为持有的值foo超出了可表示的值范围bar?
是.
具体而言,转换将产生实现定义的结果.(对于除了之外的任何值-32768,结果和行为将被很好地定义.)或者转换可以引发实现定义的信号,但我不知道任何实现这样做.
参考转换规则:N1570 6.3.1.3p3:
否则,新类型将被签名,并且值无法在其中表示; 结果是实现定义的,或者引发实现定义的信号.
只有在以下情况下才会发生
int 是16位(更准确地说,有15个值位,1个符号位,0个或更多填充位)int 使用一个补数或符号和幅度int16_t).看到满足这些标准的实现,我会感到惊讶.它必须支持二进制补码和一个补码或符号和数量,并且它必须选择后者中的一个用于类型int.(也许非二进制补码实现可能支持软件中的二进制补码,只是为了能够定义int16_t.)
如果您担心这种可能性,可以考虑将其添加到您的一个头文件中:
#include <limits.h>
#include <stdint.h>
#if !defined(INT16_MIN)
#error "int16_t is not defined"
#elif INT_MIN > INT16_MIN
#error "Sorry, I just can't cope with this weird implementation"
#endif
Run Code Online (Sandbox Code Playgroud)
该#errors为可能不会触发任何理智的现实世界中的实现.
| 归档时间: |
|
| 查看次数: |
2554 次 |
| 最近记录: |