C 中的位域,其结构包含结构体的并集

发布于 2024-10-18 00:51:50 字数 412 浏览 1 评论 0原文

嗯...为什么当我打印 sizeof(struct MyStruct) 时,这段代码会输出 3(而不是 2)?

#pragma pack(push, 1)
    struct MyStruct
    {
        unsigned char a : 6;
        union
        {
            struct
            {
                unsigned int b : 9;
            };
        };
    };
#pragma pack(pop)

万一重要的话,我在 Windows 7 x64 上运行 MinGW GCC 4.5.0,但老实说,结果对我来说很奇怪,我认为编译器和操作系统在这里并不重要。 :\

Hm... why is it that, when I print sizeof(struct MyStruct), it outputs 3 (instead of 2) for this code?

#pragma pack(push, 1)
    struct MyStruct
    {
        unsigned char a : 6;
        union
        {
            struct
            {
                unsigned int b : 9;
            };
        };
    };
#pragma pack(pop)

In case it matters, I'm running MinGW GCC 4.5.0 on Windows 7 x64, but honestly, the result is weird enough for me that I don't think the compiler and the OS matter too much here. :\

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一抹苦笑 2024-10-25 00:51:50

字段不能从非字节对齐的地址开始。
您期望:

6 bits + 9 bits -> 15 bits -> 2 bytes

但您得到的是:

6 bits -> 1 byte
9 bits -> 2 bytes
total ->  3 bytes

数据存储为:

| 1 byte | 2 byte |3 byte | 
 aaaaaaXX bbbbbbbb bXXXXX  

当您期望时:

| 1 byte | 2 byte |
 aaaaaabb bbbbbbbX  

编辑:
根据以下注释进行澄清:

联合(和包含的结构)必须是字节对齐的。内容只有 9 位并不重要,union/struct 本身就是完整的 16 位。请注意,您不能执行以下操作:

struct MyStruct
{
    unsigned char a : 6;
    union
    {
        struct
        {
            unsigned int b : 9;
        } c:9;
    } d:9;
};

因为 C 不允许您指定整个结构的位大小。

You can't have the field starting at an address that is not byte aligned.
You're expecting:

6 bits + 9 bits -> 15 bits -> 2 bytes

but what you're getting is:

6 bits -> 1 byte
9 bits -> 2 bytes
total ->  3 bytes

The data is being stored as:

| 1 byte | 2 byte |3 byte | 
 aaaaaaXX bbbbbbbb bXXXXX  

when you were expecting:

| 1 byte | 2 byte |
 aaaaaabb bbbbbbbX  

edit:
To clarify based on the comments below:

The union (and the containing struct) must be byte aligned. It doesn't matter that the contents are only 9 bits, the union/struct itself is a full 16 bits. Notice that you cannot do the following:

struct MyStruct
{
    unsigned char a : 6;
    union
    {
        struct
        {
            unsigned int b : 9;
        } c:9;
    } d:9;
};

As C won't let you specify the entire struct's bit-size.

不回头走下去 2024-10-25 00:51:50

添加@nss给出的答案——我很抱歉,如果评论在格式上没有如此限制的话,这将是一条评论:

#include <stdlib.h>

struct Test {
  unsigned short x : 6;
  unsigned short y : 1;
  unsigned short z;
};

int main( int argc, char *argv[] ) {
  printf( "sizeof( Test ) = %d\n", sizeof( struct Test ) );

  return 0;
}

它打印“4”的大小。我用 gcc、g++ 和 Sun Studio 的 CC 和 cc 进行了测试。

我并不是建议您做您正在尝试做的事情,但您可能可以通过工会做您正在尝试做的事情。我见过(但不是我自己写的)代码,看起来像这样:

struct Test {
  unsigned short x1 : 6;
  unsigned short x2 : 3;
                    : 1; // unused
  unsigned short x3 : 4;
  // ...
};

我的语法可能略有错误......但我不这么认为。

要点是:使用您想要的布局创建两个单独的结构(或结构和联合),然后在它们应该重叠的位置插入一些虚拟成员,并将它们联合在一起。

Adding to the answer given by @nss -- my apologies, this would've been a comment if comments weren't so limited on formatting:

#include <stdlib.h>

struct Test {
  unsigned short x : 6;
  unsigned short y : 1;
  unsigned short z;
};

int main( int argc, char *argv[] ) {
  printf( "sizeof( Test ) = %d\n", sizeof( struct Test ) );

  return 0;
}

It prints '4' for the size. I tested with gcc, g++, and Sun Studio's CC and cc.

Not that I recommend doing what you're attempting to do, but you could probably do what you're attempting to do with a union. I've seen (but not written myself) code that looked like this:

struct Test {
  unsigned short x1 : 6;
  unsigned short x2 : 3;
                    : 1; // unused
  unsigned short x3 : 4;
  // ...
};

I might have the syntax slightly wrong there ... but I don't think so.

Point being: create two separate structs (or a struct and a union) with the layout you were going for, then insert some dummy members where they should overlap, and union those together.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文