【问题标题】:Type of unsigned bit-fields: int or unsigned int无符号位域的类型:int 或 unsigned int
【发布时间】:2011-08-24 01:30:33
【问题描述】:

C99 标准的第 6.3.1.1 节包含:

以下内容可用于 无论int 或 可以使用unsigned int

[...] _Bool 类型的位域, intsigned intunsigned int

如果int 可以表示所有值 原始类型,值为 转换为int;否则,它 被转换为unsigned int

在我看来,这意味着unsigned int 位域被提升为int,除非无符号位域的宽度等于int 的宽度,在这种情况下最后一个短语适用。

我有以下程序:

struct S { unsigned f:32; } x = { 28349};

unsigned short us = 0xDC23L;

main(){
  int r = (x.f ^ ((short)-87)) >= us;
  printf("%d\n", r);
  return r;
}

还有两个系统来执行这个程序(int 在两个系统上都是 32 位的)。一个系统说这个程序打印 1,另一个说它打印 0。我的问题是,我应该针对这两个系统中的哪一个提交错误报告? (由于上面的摘录,我倾向于针对打印 0 的系统提交报告)

【问题讨论】:

  • (x.f ^ ((short)-87)) 在您的两个系统上的值是多少?另外,sizeof(short) 是什么?
  • @Oli 在两个系统上,-28396 如果用 %d 打印,4294938900 如果用 %u 打印。我认为这实际上更多的是表达式应该被认为具有哪种类型的问题。 sizeof(short) 是 2,chars 有 8 位。
  • 嗯,上面写着represent all values of the original *type* 我不太确定结果应该是什么。 “位域”整数类型绝对不是它们自己的类型,因此在此处输入只能指您在第二句中给出的类型。但是unsigned 将永远是未签名的。我的理解是,首先将字段隐式转换为原始类型,然后应用提升规则。
  • @Jens 我完全同意:对我来说,“宽度为 31 的位域”不是一种类型。但是我不禁注意到,如果您将32 更改为31,我尝试的所有编译器(现在是clang 1.5 和gcc 4.2.1)都会使程序返回0,这表明它们将x.f 提升为@987654346 @ 并进行签名 >= 比较。
  • 我发现了两个在这种情况下仍然返回 1 的编译器:pcctccgcc 4.4、clang 2.9、icc 12.0 和 opencc 4.2.4 的行为与您描述的一样。不过既然后面都是模仿gcc的,这个大概就不多说了。

标签: c c99 bit-fields


【解决方案1】:

标准委员会似乎已经发现了这种歧义,因为当前的草案澄清了这句话:

如果一个 int 可以表示 原始类型(受 宽度,对于位域),值 转换为int;

【讨论】:

  • 不幸的是,6.7.2 说 ...对于位域,说明符 int 指定与 signed int 相同的类型还是与 @ 相同的类型是实现定义的987654323@。那么int 位域的“原始类型”是什么?是明显的int,还是实现定义的替代品?如果int是16位宽,我们做int field : 16,如果值是0-65535,就会认为它必须转换为unsigned int;如果是-3276832767,或-3276732767,则必须转换为int。措辞很难说清楚。
  • 也不清楚这句话是否意味着如果一个位域的所有值都适合int,它必须去int。例如unsigned field : 3。这里,原始unsigned int 类型的所有值都不适合int,但它们“受宽度限制”(值0 到7)。但是在那种情况下,“原始类型”既不存在也不存在。如果意图只是“如果位域的值适合int,则它转换为int,否则转换为unsigned int”,他们为什么不直接写呢?
【解决方案2】:

我的阅读和你一样:一个 int 大小的无符号位域应该有 unsigned int 作为类型,小于它应该有signed int 类型的 int。

我访问过的编译器(x86 上的 gcc、Sparc 上的 Sun CC、POWER 上的 IBM xlC)具有与此读数相匹配的行为(在您的程序中打印 1,如果位域减少到 31 位或已签名则打印 0 )。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-28
    • 1970-01-01
    • 1970-01-01
    • 2011-05-19
    • 1970-01-01
    • 2011-07-12
    • 1970-01-01
    • 2014-04-05
    相关资源
    最近更新 更多