这个结构的大小是如何变成 4 字节的

发布于 2024-11-30 07:45:59 字数 297 浏览 1 评论 0原文

我确实有一个包含位字段的结构。根据我的说法,它是 2 个字节,但结果是 4 个字节。我已经在 stackoverflow 上阅读了一些与此相关的问题,但无法与我的问题相关。这是我确实拥有的结构

struct s{
char b;
int c:8;
};
int main()
{
printf("sizeof struct s = %d bytes \n",sizeof(struct s));
return 0;
}

,如果 int 类型必须位于其内存边界上,那么输出应该是 8 个字节,但它显示 4 个字节?

I do have a structure having bit-fields in it.Its comes out to be 2 bytes according to me but its coming out to be 4 .I have read some question related to this here on stackoverflow but not able to relate to my problem.This is structure i do have

struct s{
char b;
int c:8;
};
int main()
{
printf("sizeof struct s = %d bytes \n",sizeof(struct s));
return 0;
}

if int type has to be on its memory boundary,then output should be 8 bytes but its showing 4 bytes??

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

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

发布评论

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

评论(5

微凉徒眸意 2024-12-07 07:45:59

在此处输入图像描述

来源:http://geeksforgeeks.org/?p=9705

总之:它正在优化位的打包(这就是位字段的用途)在不影响对齐的情况下尽可能最大化。

变量的数据对齐涉及数据存储在这些存储体中的方式。例如,int在32位机器上的自然对齐是4个字节。当数据类型自然对齐时,CPU 会以最少的读取周期获取它。

同样,short int 的自然对齐是 2 个字节。这意味着,一个短整型可以存储在bank 0 –bank 1对或bank 2 –bank 3对中。 double 需要 8 个字节,并占用存储体中的两行。双精度的任何未对齐都会强制两个以上的读取周期来获取双精度数据。

请注意,双精度变量将在 32 位机器上分配在 8 字节边界上,并且需要两个内存读取周期。在 64 位机器上,根据存储体数量,双精度变量将分配在 8 字节边界上,并且只需要一个内存读取周期。

因此编译器会对每个结构体引入对齐要求。它将作为结构中最大的成员。如果您从 struct 中删除 char,您仍将获得 4 个字节

在您的 struct 中,char 是 1 字节对齐的。它后面是一个 int 位字段,它是 4 字节对齐的整数,但您定义了一个位字段。

8 位 = 1 字节。 Char 可以是任何字节边界。所以 Char + Int:8 = 2 个字节。嗯,这是一个奇数字节边界,因此编译器添加了额外的 2 个字节来维持 4 字节边界。

要使其为 8 个字节,您必须声明一个实际的 int(4 个字节)和一个 char(1 个字节)。那是 5 个字节。嗯,这是另一个奇数字节边界,因此 struct 被填充为 8 字节

我过去控制填充的常用做法是在我的 struct 之间放置填充符,以始终保持 4 字节边界。因此,如果我有一个像这样的 struct

struct s {
    int id;
    char b;
};

我将按如下方式插入分配:

struct d {
    int id;
    char b;
    char temp[3];
}

这将为我提供一个大小为 4 个字节 + 1 个字节 + 3 个字节的 struct = 8 字节!这样我就可以确保我的 struct 按照我想要的方式填充,特别是当我通过网络将其传输到某个地方时。另外,如果我改变了我的实现(例如,如果我可能将此struct保存到二进制文件中,填充符从一开始就在那里,所以只要我保持了最初的结构,一切都很好!)

最后,您可以在 带位字段的 C 结构大小以获取更多说明。

enter image description here

Source: http://geeksforgeeks.org/?p=9705

In sum: it is optimizing the packing of bits (that's what bit-fields are meant for) as maximum as possible without compromising on alignment.

A variable’s data alignment deals with the way the data stored in these banks. For example, the natural alignment of int on 32-bit machine is 4 bytes. When a data type is naturally aligned, the CPU fetches it in minimum read cycles.

Similarly, the natural alignment of short int is 2 bytes. It means, a short int can be stored in bank 0 – bank 1 pair or bank 2 – bank 3 pair. A double requires 8 bytes, and occupies two rows in the memory banks. Any misalignment of double will force more than two read cycles to fetch double data.

Note that a double variable will be allocated on 8 byte boundary on 32 bit machine and requires two memory read cycles. On a 64 bit machine, based on number of banks, double variable will be allocated on 8 byte boundary and requires only one memory read cycle.

So the compiler will introduce alignment requirement to every structure. It will be as that of the largest member of the structure. If you remove char from your struct, you will still get 4 bytes.

In your struct, char is 1 byte aligned. It is followed by an int bit-field, which is 4 byte aligned for integers, but you defined a bit-field.

8 bits = 1 byte. Char can be any byte boundary. So Char + Int:8 = 2 bytes. Well, that's an odd byte boundary so the compiler adds an additional 2 bytes to maintain the 4-byte boundary.

For it to be 8 bytes, you would have to declare an actual int (4 bytes) and a char (1 byte). That's 5 bytes. Well that's another odd byte boundary, so the struct is padded to 8 bytes.

What I have commonly done in the past to control the padding is to place fillers in between my struct to always maintain the 4 byte boundary. So if I have a struct like this:

struct s {
    int id;
    char b;
};

I am going to insert allocation as follows:

struct d {
    int id;
    char b;
    char temp[3];
}

That would give me a struct with a size of 4 bytes + 1 byte + 3 bytes = 8 bytes! This way I can ensure that my struct is padded the way I want it, especially if I transmit it somewhere over the network. Also, if I ever change my implementation (such as if I were to maybe save this struct into a binary file, the fillers were there from the beginning and so as long as I maintain my initial structure, all is well!)

Finally, you can read this post on C Structure size with bit-fields for more explanation.

唐婉 2024-12-07 07:45:59

int c:8; 表示您正在声明一个大小为 8 位的位域。由于 32 位系统上的alignemt 通常为 4 个字节(=32 位),因此您的对象将显示为 4 个字节而不是 2 个字节(char + 8 位)。

int c:8; means that you are declaring a bit-field with the size of 8 bits. Since the alignemt on 32 bit systems is normally 4 bytes (=32 bits) your object will appear to have 4 bytes instead of 2 bytes (char + 8 bit).

£冰雨忧蓝° 2024-12-07 07:45:59

但如果你指定c应该占用8位,那么它就不是真正的int了,不是吗? c + b 的大小为 2 个字节,但编译器将结构填充为 4 个字节。

But if you specify that c should occupy 8 bits, it's not really an int, is it? The size of c + b is 2 bytes, but your compiler pads the struct to 4 bytes.

冷月断魂刀 2024-12-07 07:45:59

结构体中字段的对齐方式取决于编译器/平台。
也许您的编译器对长度小于或等于 16 位的位域使用 16 位整数,也许它永远不会在小于 4 字节边界的任何内容上对齐结构。

底线:如果您想了解结构体字段如何对齐,您应该阅读您正在使用的编译器和平台的文档。

They alignment of fields in a struct is compiler/platform dependent.
Maybe your compiler uses 16-bit integers for bitfields less than or equal to 16 bits in length, maybe it never aligns structs on anything smaller than a 4-byte boundary.

Bottom line: If you want to know how struct fields are aligned you should read the documentation for the compiler and platform you are using.

风筝在阴天搁浅。 2024-12-07 07:45:59

在通用的、平台无关的 C 语言中,您永远无法知道结构体/联合体的大小,也无法知道位域的大小。编译器可以在结构/联合/位字段内的任何位置自由添加任意数量的填充字节,除了第一个内存位置。

此外,编译器还可以自由地向位域添加任意数量的填充,并且可以将它们放置在任何它喜欢的地方,因为哪个位是 msb 和 lsb 不是由 C 定义的

。说到位域,你会被 C 语言冷落,因为它们没有标准。您必须详细阅读编译器文档以了解它们在您的特定平台上的行为方式,并且它们是完全不可移植的。

明智的解决方案是永远不要使用位字段,它们是 C 的冗余功能。相反,请使用按位运算符。按位运算符和深入记录的位字段将生成相同的机器代码(未记录的位字段可以自由地生成相当任意的代码)。但按位运算符保证在世界上任何编译器/系统上都能以相同的方式工作。

In generic, platform-independent C, you can never know the size of a struct/union nor the size of a bit-field. The compiler is free to add as many padding bytes as it likes anywhere inside the struct/union/bit-field, except at the very first memory location.

In addition, the compiler is also free to add any number of padding bits to a bit-field, and may put them anywhere it likes, because which bit is msb and lsb is not defined by C.

When it comes to bit-fields, you are left out in the cold by the C language, there is no standard for them. You must read compiler documentation in detail to know how they will behave on your specific platform, and they are completely non-portable.

The sensible solution is to never ever use bit fields, they are a reduntant feature of C. Instead, use bit-wise operators. Bit-wise operators and in-depth documented bit-fields will generate the same machine code (non-documented bit-fields are free to result in quite arbitrary code). But bit-wise operators are guaranteed to work the same on any compiler/system in the world.

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