ANSI C是否支持有符号/无符号位字段?

将位字段限定为有符号/无符号是否有意义?

标准的相关部分(ISO / IEC 9899:1999)是6.7.2.1#4:

位字段的类型应为_Bool,signed int,unsigned int或其他实现定义类型的限定或非限定版本。

是。 这里有一个例子:

struct { /* field 4 bits wide */ unsigned field1 :4; /* * unnamed 3 bit field * unnamed fields allow for padding */ unsigned :3; /* * one-bit field * can only be 0 or -1 in two's complement! */ signed field2 :1; /* align next field on a storage unit */ unsigned :0; unsigned field3 :6; }full_of_fields; 

只有你知道你的项目是否有意义; 通常情况下,如果字段可以有意义地为负,则它适用于具有多个位的字段。

将变量限定为有符号或无符号非常重要。 编译器需要知道在比较和转换过程中如何处理变量。 检查此代码的输出:

 #include  typedef struct { signed s : 1; unsigned u : 1; } BitStruct; int main(void) { BitStruct x; xs = 1; xu = 1; printf("s: %d \tu: %d\r\n", xs, xu); printf("s>0: %d \t u>0: %d\r\n", xs > 0, xu > 0); return 0; } 

输出:

 s: -1 u: 1 s>0: 0 u>0: 1 

编译器使用单个位1或0存储变量。对于有符号变量,最高有效位确定符号(高值处理为负)。 因此,签名变量虽然以二进制forms存储为1,但它被解释为负数。

扩展此主题,无符号两位数的范围为0到3,而带符号的两位数的范围为-2到1。

我不认为安德鲁正在谈论单比特位字段。 例如,4位字段:3位数字信息,1位用于符号。 这完全有道理,尽管我承认无法想出这样的情况。

更新:我不是说我不能想到多比特位字段的使用(在2400bps调制解调器时间里一直使用它们来尽可能地压缩数据进行传输),但我想不到用于签名位字段,尤其不是一个古怪的,明显的,对读者来说是一个“aha”时刻。

大多数情况下,ANSI-C提供有符号和无符号位字段。 这是必需的。 这也是为IEEE-754浮点类型[[1] [5] [10]],[[1] [8] [23]]和[[1] [10] [53]编写调试器覆盖的一部分。 ]。 这在此类数据的机器类型或网络转换中非常有用,或者在通过链接(如video卡纹理)发送之前将转换双倍(64位用于数学)检查到半精度(16位用于压缩)。

 // Fields need to be reordered based on machine/compiler endian orientation typedef union _DebugFloat { float f; unsigned long u; struct _Fields { signed s : 1; unsigned e : 8; unsigned m : 23; } fields; } DebugFloat; 

埃里克

是的,它可以。 C位字段基本上只是有限范围的整数。 通常硬件接口将位组合在一起,以至于某些控制可以从例如-8到7,在这种情况下,您需要一个有符号的位字段,或者从0到15,在这种情况下,您需要一个无符号位 – 领域。

签名位域有用的一个地方是仿真,其中仿真机器的位数少于默认字节。

我目前正在考虑模拟一个48位的机器,如果通过位域使用64位“long long”中的48位是合理的,我会尝试解决…生成的代码就像我一样做了所有的掩蔽,符号扩展等明确但它会读得更好……

位屏蔽签名类型因平台硬件和平台硬件而异,因为它可以处理来自移位的溢出等。

任何半个好的QA工具都会故意警告这种用法。

如果’bit’被签名,那么你有一个-1,0,1的范围,然后它变成三进制数字。 我不认为这里的标准缩写在这里是合适的,但是可以进行有趣的对话:)