简体   繁体   English

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

[英]Does ANSI C support signed / unsigned bit fields?

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

The relevant portion of the standard (ISO/IEC 9899:1999) is 6.7.2.1 #4: 标准(ISO / IEC 9899:1999)的相关部分是6.7.2.1#4:

A bit-field shall have a type that is a qualified or unqualified version of _Bool, signed int, unsigned int, or some other implementation-defined type. 位域的类型必须是_Bool的合格或不合格版本,signed int,unsigned int或其他一些实现定义的类型。

Yes. 是。 An example from here : 来自这里的一个例子:

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;

Only you know if it makes sense in your projects; 只有您知道在您的项目中是否有意义; typically, it does for fields with more than one bit, if the field can meaningfully be negative. 通常,如果该字段可以有意义地为负数,则它适用于多于一位的字段。

It's very important to qualify your variables as signed or unsigned. 将变量限定为有符号或无符号非常重要。 The compiler needs to know how to treat your variables during comparisons and casting. 编译器需要知道在比较和转换期间如何处理变量。 Examine the output of this code: 检查此代码的输出:

#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;
}

Output: 输出:

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

The compiler stores the variable using a single bit, 1 or 0. For signed variables, the most significant bit determines the sign (high is treated negative). 编译器仅使用1或0来存储变量。对于有符号变量,最高有效位确定符号(高被视为负)。 Thus, the signed variable, while it gets stored as 1 in binary, it gets interpreted as negative one. 因此,有符号变量以二进制形式存储为1时,却被解释为负数。

Expanding on this topic, an unsigned two bit number has a range of 0 to 3, while a signed two bit number has a range of -2 to 1. 在此主题上扩展,无符号的两位数的范围为0到3,而有符号的两位数的范围为-2到1。

I don't think Andrew is talking about single-bit bit fields. 我认为安德鲁不是在谈论单位比特字段。 For example, 4-bit fields: 3 bits of numerical information, one bit for sign. 例如,4位字段:3位数字信息,一位符号。 This can entirely make sense, though I admit to not being able to come up with such a scenario off the top of my head. 尽管我承认无法提出这样的方案,但这完全是有道理的。

Update: I'm not saying I can't think of a use for multi-bit bit fields (having used them all the time back in 2400bps modem days to compress data as much as possible for transmission), but I can't think of a use for signed bit fields, especially not a quaint, obvious one that would be an "aha" moment for readers. 更新:我并不是说我无法想到多位位域的用途(在2400bps调制解调器时代一直使用它们来尽可能多地压缩数据以进行传输),但是我想不到用于带符号位字段的一种用法,特别是不是古朴的,明显的用法,对于读者来说,这将是一个“啊哈”时刻。

Most certainly ANSI-C provides for signed and unsigned bit fields. 无疑,ANSI-C提供了有符号和无符号位字段。 It is required. 它是必需的。 This is also part of writing debugger overlays for IEEE-754 floating point types [[1][5][10]], [[1][8][23]], and [[1][10][53]]. 这也是编写针对IEEE-754浮点类型[[1] [5] [10]],[[1] [8] [23]]和[[1] [10] [53]的调试器覆盖的一部分]。 This is useful in machine type or network translations of such data, or checking conversions double (64 bits for math) to half precision (16 bits for compression) before sending over a link, like video card textures. 这在机器类型或此类数据的网络转换中,或在通过链接(如视频卡纹理)发送之前,检查转换是否是双精度转换(数学上为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;

Eric 埃里克

Yes, it can. 是的,它可以。 C bit-fields are essentially just limited-range integers. C位字段本质上只是有限范围的整数。 Frequently hardware interfaces pack bits together in such away that some control can go from, say, -8 to 7, in which case you do want a signed bit-field, or from 0 to 15, in which case you want an unsigned bit-field. 通常,硬件接口将位打包在一起,以便某些控制可以从-8到7,在这种情况下,您确实需要有符号的位域,或者从0到15,在这种情况下,您需要无符号的位-领域。

One place where signed bitfields are useful is in emulation, where the emulated machine has fewer bits than your default word. 有符号位域有用的一个地方是在仿真中,其中仿真的机器的位数少于默认字的位数。

I'm currently looking at emulating a 48-bit machine and am trying to work out if it's reasonable to use 48 bits out of a 64-bit "long long" via bitfields... the generated code would be the same as if I did all the masking, sign-extending etc explicitly but it would read a lot better... 我目前正在仿真48位计算机,并尝试找出通过位域在64位“ long long”中使用48位是否合理……生成的代码与我所使用的相同做了所有的掩蔽,符号扩展等,但是它读起来好多了...

Bit masking signed types varies from platform hardware to platform hardware due to how it may deal with an overflow from a shift etc. 由于平台掩码可能会处理由于移位等引起的溢出,因此位掩码签名类型因平台硬件而异。

Any half good QA tool will warn knowingly of such usage. 任何一半好的质量检查工具都会在使用时警告您。

if a 'bit' is signed, then you have a range of -1, 0, 1, which then becomes a ternary digit. 如果对“位”进行了签名,则您的范围为-1、0、1,然后变成三进制数字。 I don't think the standard abbreviation for that would be suitable here, but makes for interesting conversations :) 我认为在此不适合使用标准缩写,但可以进行有趣的对话:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM