Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么不';正常变量是否允许使用t位字段?_C_Gcc_Struct_Unions_Bit Fields - Fatal编程技术网

C 为什么不';正常变量是否允许使用t位字段?

C 为什么不';正常变量是否允许使用t位字段?,c,gcc,struct,unions,bit-fields,C,Gcc,Struct,Unions,Bit Fields,我想知道为什么位字段与联合/结构一起工作,而不与正常变量一起工作,如int或short 这项工作: struct foo { int bar : 10; }; 但这失败了: int bar : 10; // "Expected ';' at end of declaration" 为什么此功能仅在联合/结构中可用,而不在变量中可用?技术上不一样吗 编辑: 如果允许的话,您可以创建一个包含3个字节的变量,而不必每次都使用struct/union成员。这就是我如何使用struct创建它

我想知道为什么位字段与联合/结构一起工作,而不与正常变量一起工作,如
int
short

这项工作:

struct foo {
    int bar : 10;
};
但这失败了:

int bar : 10; // "Expected ';' at end of declaration"
为什么此功能仅在联合/结构中可用,而不在变量中可用?技术上不一样吗


编辑:

如果允许的话,您可以创建一个包含3个字节的变量,而不必每次都使用struct/union成员。这就是我如何使用struct创建它的方法:

struct int24_t {
    int x : 24 __attribute__((packed));
};

struct int24_t var; // sizeof(var) is now 3
// access the value would be easier:
var.x = 123;

因为它没有意义。位字段声明用于在
结构的字段之间共享和重新组织位。例如,如果没有成员,只有一个恒定大小的变量(由实现定义),那么将几乎可以确定为8位宽的
字符声明为一个1位或2位变量是矛盾的。这是一个主观的问题,“规范为什么这么说?”但我要试一试

函数中的变量通常具有“自动”存储,而不是其他持续时间(静态持续时间、线程持续时间和分配的持续时间)

在结构中,显式定义某个对象的内存布局。但在函数中,编译器会以某种未指定的方式自动将存储分配给变量。这里有一个问题:
x
在堆栈上占用多少字节

// sizeof(unsigned) == 4
unsigned x;
它可以占用4个字节,也可以占用8、12或0个字节,或者可以同时放在三个不同的寄存器中,或者堆栈和一个寄存器,或者堆栈上有四个位置

关键是编译器正在为您进行分配。由于您没有进行堆栈布局,因此不应指定位宽度

扩展讨论:位字段实际上有点特殊。该规范规定相邻的位字段被打包到同一存储单元中。位字段实际上不是对象

  • 不能
    sizeof()
    位字段

  • 不能
    malloc()
    位字段

  • 位字段不能
    &addressof

  • 所有这些都可以在C中使用对象,但不能使用位字段。位域是一种特殊的东西,它只针对结构而不是其他任何地方

    关于
    int24_ut
    (更新):
    它在某些架构上工作,但不适用于其他架构。它甚至连一点便携性都没有

    typedef struct {
        int x : 24 __attribute__((packed));
    } int24_t;
    
    在Linux ELF/x64、OS X/x86、OS X/x64上,
    sizeof(int24\u t)==3
    。但是在OSX/PowerPC上,
    sizeof(int24\u t)==4

    注意:GCC为加载
    int24\t
    生成的代码基本上与此等效:

    int result = (((char *) ptr)[0] << 16) |
                 (((unsigned char *) ptr)[1] << 8) |
                 ((unsigned char *)ptr)[2];
    

    int结果=((char*)ptr)[0]结构或联盟的成员在其存储位置之间有关系。由于布局受到严格限制,编译器无法以巧妙的方式重新排序或打包它们以节省空间;基本上,编译器在布局结构时唯一的自由是在对齐所需的量之外添加额外填充的自由。Bit字段允许您通过承诺(1)您不需要这些成员的地址,以及(2)您不需要将值存储在某个限定范围之外,从而手动为编译器提供更大的自由来紧密打包信息


    如果您谈论的是单个变量而不是结构成员,那么在抽象机器中,它们的存储位置之间没有关系。如果它们是函数中的本地自动变量,并且它们的地址从未被获取,那么编译器可以自由地将它们保存在寄存器中或将它们打包在内存中手动向编译器提供这样的提示几乎没有什么好处。

    如果一个结构包含四个2位的位字段组合成一个字节,那么每次使用该结构时,与仅包含四个
    un类型字段的结构相比,将节省三个字节有符号字符
    。如果声明一个数组
    QBLOB myArray[1000000]
    ,这样一个数组只需要1000000字节;如果QBLOB是一个包含四个
    无符号字符
    字段的结构,它将需要更多的3000000字节。因此,使用位字段的能力可能会节省大量内存

    相比之下,在大多数体系结构上,将简单变量声明为最佳大小的位字段类型,与将其声明为最小合适的标准整数类型相比,最多可以节省15位。由于访问位字段通常需要比访问标准整数类型的变量更多的代码,因此很少有情况下将单个变量声明为位字段将提供任何优势

    不过,这一原则有一个明显的例外:某些体系结构包含的功能可以设置、清除和测试单个位,其效率甚至超过读取和写入字节的效率。某些此类体系结构的编译器包含一个
    类型,并将该类型的八个变量打包到存储器的每个字节中。Such变量通常被限制在静态或全局范围内,因为处理它们的专用指令可能被限制在使用特定的内存区域(链接器可以确保将任何此类变量放置在它们必须去的地方)一个完整的词


    没有技术上的原因可以解释为什么不能扩展C语法来定义结构(AFAIK)之外的位字段,但它们的实用性值得怀疑,因为它所涉及的工作量太大了。

    Uh,因为它没有意义