为什么普通变量不允许位域? [英] Why aren't bitfields allowed with normal variables?

查看:24
本文介绍了为什么普通变量不允许位域?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道为什么位域适用于联合/结构,而不适用于像 intshort 这样的普通变量.
这有效:

I wonder why bitfields work with unions/structs but not with a normal variable like int or short.
This works:

struct foo {
    int bar : 10;
};

但这失败了:

int bar : 10; // "Expected ';' at end of declaration"

为什么此功能仅在联合/结构中可用,而在变量中不可用?技术上不一样吗?

Why is this feature only available in unions/structs and not with variables? Isn't it technical the same?

如果允许,您可以创建一个具有 3 个字节的变量,而无需每次都使用 struct/union 成员.这就是我对结构的处理方式:

If it would be allowed you could make a variable with 3 bytes for instance without using the struct/union member each time. This is how I would to it with a 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;

推荐答案

这是一个主观问题,为什么规范这么说?"但我会试一试.

This is a subjective question, "Why does the spec say this?" But I'll give it my shot.

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

Variables in a function normally have "automatic" storage, as opposed to one of the other durations (static duration, thread duration, and allocated duration).

在结构体中,您明确定义了某个对象的内存布局.但是在函数中,编译器会以某种未指定的方式自动为变量分配存储空间.这里有一个问题:x 在栈上占用了多少字节?

In a struct, you are explicitly defining the memory layout of some object. But in a function, the compiler automatically allocates storage in some unspecified manner to your variables. Here's a question: how many bytes does x take up on the stack?

// sizeof(unsigned) == 4
unsigned x;

它可以占用 4 个字节,也可以占用 8、12 或 0,或者它可以同时放置在三个不同的寄存器中,或者堆栈和一个寄存器中,或者它可以放置四个位置在堆栈上.

It could take up 4 bytes, or it could take up 8, or 12, or 0, or it could get placed in three different registers at the same time, or the stack and a register, or it could get four places on the stack.

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

The point is that the compiler is doing the allocation for you. Since you are not doing the layout of the stack, you should not specify the bit widths.

扩展讨论:位域实际上有点特殊.该规范指出相邻的位域被打包到同一个存储单元中.位域实际上并不是对象.

Extended discussion: Bitfields are actually a bit special. The spec states that adjacent bitfields get packed into the same storage unit. Bitfields are not actually objects.

  1. 你不能sizeof()一个位域.

你不能malloc()一个位域.

你不能&addressof一个位域.

所有这些事情你都可以用 C 中的对象来完成,但不能用位域来完成.位域是一种特殊的东西,专为结构而生,其他地方都没有.

All of these things you can do with objects in C, but not with bitfields. Bitfields are a special thing made just for structures and nowhere else.

关于int24_t(更新):它适用于某些架构,但不适用于其他架构.它甚至稍微便携.

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

在 Linux ELF/x64、OS X/x86、OS X/x64 上,sizeof(int24_t) == 3.但在 OS X/PowerPC 上,sizeof(int24_t) == 4.

On Linux ELF/x64, OS X/x86, OS X/x64, sizeof(int24_t) == 3. But on OS X/PowerPC, sizeof(int24_t) == 4.

注意 GCC 为加载 int24_t 生成的代码基本上等同于:

Note the code GCC generates for loading int24_t is basically equivalent to this:

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

这是 x64 上的 9 条指令,只是为了加载一个值.

It's 9 instructions on x64, just to load a single value.

这篇关于为什么普通变量不允许位域?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆