【问题标题】:Type punning a positive signed integer into an unsigned (and vice versa)将带符号的正整数键入无符号(反之亦然)
【发布时间】:2019-03-17 16:50:21
【问题描述】:
union   Positive_Small {
    int8_t  s;
    uint8_t u;
};

union Positive_Small    x = {.s = 3};
union Positive_Small    y = {.u = 4};

assert(x.u == 3);
assert(y.s == 4);

这是定义的行为吗? 标准是否保证有符号整数类型的正范围与其无符号等效项具有相同的表示形式?

我想没有足够疯狂的实现(也许是 DS9K?)不这样做,但它是否已定义?

【问题讨论】:

  • 在某些平台上,使用偏移二进制表示(例如,对于 16 位,位模式 x0000、0x8000 和 0xFFFF 将分别表示 -32768、0 和 +32767)可以提供显着的性能比较繁重的代码的优势。标准不允许,但如果是的话,它几乎不会是 DS9K。

标签: c language-lawyer unsigned signed type-punning


【解决方案1】:

简而言之,是的——标准保证对于共享的正值范围,无符号类型的值的按位表示与有符号类型的值相同。

C11 Section 6.2.5 Types 定义了这一点(以及许多其他术语和行为):

¶6 对于每个有符号整数类型,都有一个对应的(但不同的)无符号整数类型(用关键字unsigned 指定)使用相同的存储量(包括符号信息)并具有相同的对齐方式要求。 _Bool 类型和对应于标准有符号整数类型的无符号整数类型是标准无符号整数类型。对应于扩展有符号整数类型的无符号整数类型是扩展无符号整数类型。标准和扩展的无符号整数类型统称为无符号整数类型40)

¶9 有符号整数类型的非负值范围是对应无符号整数类型的子范围,相同值在每种类型中的表示是相同的。41) 一个计算涉及无符号操作数的操作数永远不会溢出,因为无法由生成的无符号整数类型表示的结果会以比结果类型可以表示的最大值大一的数字为模减少。

40) 因此,本标准中关于无符号整数类型的任何声明也适用于扩展的无符号整数类型。

41) 相同的表示和对齐要求意味着作为函数的参数、函数的返回值和联合成员的可互换性。

具体如dbushpointed outsection 6.2.6 Representation of typessection 6.2.6.2 Integer types,还包含相关信息:

¶2 对于有符号整数类型,对象表示的位应分为三组:值位、填充位和符号位。不需要任何填充位; signed char 不应有任何填充位。应该有一个符号位。作为值位的每个位都应与相应无符号类型的对象表示中的相同位具有相同的值(如果有符号类型中有 M 个值位并且 N em> 为无符号类型,则 M ≤ N)。如果符号位为零,则不应影响结果值。如果符号位为 1,则按以下方式之一修改该值:

  • 符号位为0的对应值取反(符号和幅度);
  • 符号位的值为 -(2M) (二的补码);
  • 符号位的值是 -(2M- 1) (个数的补码)。

这些应用中的哪一个是实现定义的,无论符号位为 1 且所有值位为零(对于前两个),还是符号位和所有值位为 1(对于一个补码)的值是陷阱表示或正常值。在符号和幅度以及一个的补码的情况下,如果这个表示是一个正常值,它被称为一个负零

【讨论】:

  • 6.2.6.2p2 也是相关的。
猜你喜欢
  • 2011-08-09
  • 2011-10-14
  • 1970-01-01
  • 1970-01-01
  • 2019-07-23
  • 1970-01-01
  • 2011-11-08
  • 1970-01-01
  • 2013-05-21
相关资源
最近更新 更多