13

在C99 标准的第 7.18.1.1 节第 1 段中:

typedef 名称intN_t指定宽度为N的有符号整数类型,无填充位和二进制补码表示。

根据 C99 标准,精确宽度的有符号整数类型需要具有二进制补码表示。这意味着,例如,int8_t的补码-128最小值相反,最小值为。-127

第 6.2.6.2 节第 2 段允许实现决定是否将符号位解释为符号和幅度二进制补码二进制补码

如果符号位为 1,则应通过以下方式之一修改该值:
— 符号位为 0 的对应值取反(符号和幅度);
— 符号位的值为 -(2 N )(二进制补码);
— 符号位的值为 -(2 N - 1)(个数补码)。

方法之间的区别很重要,因为二进制补码( ) 中整数的最小值-128可能超出二进制补码( -127to 127) 中可表示的值范围。

假设一个实现将int类型定义为具有ones' complement表示,而该int16_t类型具有two's complementC99 标准所保证的表示。

int16_t foo = -32768;
int bar = foo;

在这种情况下,从int16_t到的转换是否int会导致实现定义的行为,因为 持有的值foo超出了 可表示的值范围bar

4

1 回答 1

8

是的。

具体来说,转换将产生实现定义的结果。(对于除 之外的任何值-32768,结果和行为都将得到很好的定义。)或者转换可能会引发实现定义的信号,但我不知道有任何实现会这样做。

转换规则参考:N1570 6.3.1.3p3:

否则,新类型是有符号的,值不能在其中表示;结果要么是实现定义的,要么是产生实现定义的信号。

只有在以下情况下才会发生这种情况:

  • int是 16 位(更准确地说,有 15 个值位、1 个符号位和 0 个或更多填充位)
  • int使用补码或符号和大小
  • 该实现还支持二进制补码(否则它不会定义int16_t)。

我会惊讶地看到满足这些标准的实现。它必须同时支持二进制补码和一个补码或符号和大小,并且必须为 type 选择后者之一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

#errors 不太可能触发任何理智的现实世界实施。

于 2013-08-07T19:46:24.090 回答