将位字段限定为有符号/无符号是否有意义?
10 回答
标准的相关部分 (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 <stdio.h>
typedef struct
{
signed s : 1;
unsigned u : 1;
} BitStruct;
int main(void)
{
BitStruct x;
x.s = 1;
x.u = 1;
printf("s: %d \t u: %d\r\n", x.s, x.u);
printf("s>0: %d \t u>0: %d\r\n", x.s > 0, x.u > 0);
return 0;
}
输出:
s: -1 u: 1
s>0: 0 u>0: 1
编译器使用单个位 1 或 0 存储变量。对于有符号变量,最高有效位确定符号(高位被视为负数)。因此,带符号的变量,虽然它以二进制形式存储为 1,但它被解释为负值。
扩展此主题,无符号两位数的范围为 0 到 3,而有符号两位数的范围为 -2 到 1。
我不认为安德鲁在谈论单比特位域。例如,4 位字段:3 位数字信息,1 位符号。这完全是有道理的,尽管我承认无法在我的脑海中想出这样的场景。
更新:我并不是说我想不出多位位字段的用途(在 2400bps 调制解调器时代一直使用它们来尽可能地压缩数据以进行传输),但我想不出有符号位字段的用途,尤其是不是一个古怪的、明显的,对读者来说将是一个“啊哈”的时刻。
是的,它可以。C 位域本质上只是有限范围的整数。硬件接口经常将位打包在一起,使得某些控制可以从 -8 到 7,在这种情况下您确实需要一个有符号位字段,或者从 0 到 15,在这种情况下您需要一个无符号位 -场地。
最肯定的是 ANSI-C 提供有符号和无符号位字段。这是必需的。这也是为 IEEE-754 浮点类型 [[1][5][10]]、[[1][8][23]] 和 [[1][10][53] 编写调试器覆盖的一部分]。这在此类数据的机器类型或网络转换中很有用,或者在通过链接发送之前检查双精度(数学为 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;
埃里克
有符号位域有用的一个地方是在仿真中,其中仿真机器的位数少于您的默认字。
我目前正在考虑模拟 48 位机器,并试图通过位域从 64 位“long long”中使用 48 位是否合理......生成的代码将与我相同做了所有的屏蔽,符号扩展等,但它会读起来更好......
根据这个参考,有可能: http:
//publib.boulder.ibm.com/infocenter/macxhelp/v6v81/index.jsp ?topic=/com.ibm.vacpp6m.doc/language/ref/clrc03defbitf.htm
位掩码签名类型因平台硬件而异,这取决于它如何处理移位溢出等。
任何半好 QA 工具都会故意警告这种用法。
如果一个“位”被签名,那么你的范围是-1、0、1,然后变成一个三进制数字。我认为标准缩写在这里不合适,但可以进行有趣的对话:)