POSIX是什么意思"两个补码表示"在stdint.h?

时间:2017-08-09 06:59:24

标签: c posix language-lawyer

众所周知,有符号整数溢出会调用未定义的行为,并且对有符号整数的逐位操作最多也是不可靠的。因此,我发现the POSIX standard中的这一行很奇怪:

  

typedef name int N _t指定一个有符号整数类型,其宽度为N,没有填充位,和一个二进制补码表示。因此,int8_t表示一个有符号整数类型,带有正好是8位的宽度。

这是一个相当模糊的陈述,可能意味着这些事情的任何组合:

  1. intN_t的范围是INTN_MININTN_MAX
  2. sizeof(intN_t) == N/8
  3. intN_t上的按位运算与双补码表示的预期行为相同。在每个地方插入-1 ^ x == ~x演员后,每x intN_t。{/ li>
  4. intN_t不能有陷阱表示(优化编译器不得利用可能的陷阱)。
  5. intN_t变量的溢出是已定义的行为(并从INTN_MAX换行到INTN_MIN)。
  6. 基于文档的其余部分,

    (1)和(2)对我来说都显得非常明显。 (1)由INTN_MIN / MAX的定义明确指定。 (2)隐含在"没有填充位。"

    POSIX是否需要(3),(4)和(5)中的哪一个?

1 个答案:

答案 0 :(得分:9)

TL; DR

在<{1}}存在的任何C99,C11编译器中, 1 3 4 为true。 2 在任何存在intN_t的C11编译器中都是如此 - 因为int8_t的存在意味着int8_t为8。 5 特别是C不需要 - 未定义有符号整数溢出的行为。

POSIX限制允许的C实现,以便CHAR_BIT必须为8,整数表示是2的补码。因此,POSIX平台上的兼容C99 / C11编译器必须具有CHAR_BIT,这使得语句 1 2 3 和<在POSIX上为true> 4 为true。由于POSIX没有说明有符号整数溢出,因此它仍未定义,因此 5 为假。

引用的句子是从C11(C99)标准中取得 verbatim C11 7.20.1.1p1

  

typedef名称int8_t指定有符号整数类型,宽度为intN_t,没有填充位,以及二进制补码表示。因此,N表示这样的有符号整数类型,其宽度恰好为8位。

int8_t在C中是可选,因此标准中仅存在此片段甚至不需要2的补码表示。 C11 7.20.1.1p3

  

这些类型是可选的。但是,如果实现提供宽度为8,16,32或64位的整数类型,没有填充位,并且(对于具有二进制补码表示的有符号类型),它应定义相应的typedef名称。

你原来的陈述,

  1. 当然是正确的,但这样的事情并不是来自两个补充表示。任何一个补码架构上的int8_t范围从intINT_MIN。但是,由此得出的结论是INT_MAX的值为

  2. 来自两个补码表示INTN_MINsizeof(intN_t)。但是,POSIX要求N / CHAR_BIT为8,因此CHAR_BIT确实是sizeof(intN_t)

  3. 这是两个补充表示

  4. 的唯一内容
  5. 来自一个二进制补码,但是2&是补码的组合,并且没有填充位。

  6. 跟随双向补充表示既不是C也不是POSIX 。< / p>

  7. POSIX没有指定类型N / 8,而是POSIX采用和扩充的C99,C11。 POSIX增加了两个限制:   *即使C编程语言允许,int8_t必须精确为8而不是更大   *不允许使用单数补码或整数的符号和幅度表示,即使它们是C编程语言允许的

    C99,C11指定如果存在,类型CHAR_BIT必须具有完全如此多的位,没有填充位,以及2&#39; s补码。如果intN_t存在,则其int8_t必须为1,因为它是sizeof的同义词,然后signed char等于8。

    不会有CHAR_BIT的陷阱表示,但它并不意味着具有明确不确定值的那些对象必须具有相同的值,或者传递库函数的这些值将具有已定义的行为。请考虑以下片段:

    intN_t

    编译器甚至不需要调用int32_t *foo = malloc(sizeof(int32_t)); printf(PRId32 "\n", *foo); printf(PRId32 "\n", *foo); free(foo); ;即使没有malloc类型的陷阱值,它也可以将其编译为等效的puts("42\n666");。这是因为malloc

      

    [...]为大小由大小指定的对象分配空间,的值为不确定

    不确定意味着unstable; indeterminable

    有符号整数溢出的行为始终未定义。