gpt4 book ai didi

C- 使用位域时结构的大小以及它在内存中的存储方式

转载 作者:太空狗 更新时间:2023-10-29 15:19:59 25 4
gpt4 key购买 nike

void main()
{
struct bitfield
{
signed int a :3;
unsigned int b :13;
unsigned int c :1;
};

struct bitfield bit1 = { 2, 14, 1 };
clrscr();
printf("%d", sizeof(bit1));
getch();
}

为什么这里的大小是 4 个字节?这些元素究竟是如何存储在内存中的?

最佳答案

几乎位域的每个方面都是实现定义的。甚至“普通 int”位字段的符号也是实现定义的;它可能已签名或未签名。字段的布局——无论它们是从包含“单元”(标准中使用的术语)中的最高有效位到最低有效位,还是从最低有效位到最高有效位,都是由实现定义的。最大允许位域的大小;当位字段存储在新单元中时;所有这些都是实现定义的。

例如,在使用 GCC 4.8.1 的 Mac OS X 10.8.4 上,可以证明问题中的 struct bitfield 是用 a 布局的占用 3 个最低有效位(位 0-2),b 占用接下来的 13 位(3-15),c 占用接下来的 1 位(16):

#include <stdio.h>

static void print_info(int v);

int main(void)
{
int values[] =
{
0x55555555, 0xAAAAAAAA, 0x87654321, 0xFEDCBA98,
0xFEDCBA90, 0xFEDCBA91, 0xFEDCBA92, 0xFEDCBA93,
0xFEDCBA94, 0xFEDCBA95, 0xFEDCBA96, 0xFEDCBA97,
0xFEDCBA98, 0xFEDCBAA0, 0xFEDCBAA8, 0x0000BAA0,
0x0001BAA0, 0x00000008, 0x00000010, 0x00000018,
0x0000FFF0, 0x0000FFF8,
};

for (size_t i = 0; i < sizeof(values)/sizeof(values[0]); i++)
print_info(values[i]);
return 0;
}

static void print_info(int v)
{
union
{
unsigned int x;
struct bitfield
{
signed int a:3;
unsigned int b:13;
unsigned int c:1;
} y;
} u;
u.x = v;
printf("0x%.8X => %2d 0x%.4X %1X\n", u.x, u.y.a, u.y.b, u.y.c);
}

示例输出:

0x55555555 => -3 0x0AAA 1
0xAAAAAAAA => 2 0x1555 0
0x87654321 => 1 0x0864 1
0xFEDCBA98 => 0 0x1753 0
0xFEDCBA90 => 0 0x1752 0
0xFEDCBA91 => 1 0x1752 0
0xFEDCBA92 => 2 0x1752 0
0xFEDCBA93 => 3 0x1752 0
0xFEDCBA94 => -4 0x1752 0
0xFEDCBA95 => -3 0x1752 0
0xFEDCBA96 => -2 0x1752 0
0xFEDCBA97 => -1 0x1752 0
0xFEDCBA98 => 0 0x1753 0
0xFEDCBAA0 => 0 0x1754 0
0xFEDCBAA8 => 0 0x1755 0
0x0000BAA0 => 0 0x1754 0
0x0001BAA0 => 0 0x1754 1
0x00000008 => 0 0x0001 0
0x00000010 => 0 0x0002 0
0x00000018 => 0 0x0003 0
0x0000FFF0 => 0 0x1FFE 0
0x0000FFF8 => 0 0x1FFF 0

测试值并非完全随机选择。从测试值0xFEDCBA90到0xFECBA97,我们可以看到最低有效3位包含a。从测试值0x0000BAA0和0x0001BAA0,我们可以看出第17位(或第16位)包含c。从测试值 0x00000008 到 0x0000FFF8,我们可以看到第 3-15 位包含 b

然而,必须指出的是,代码在理论上的可移植性值得商榷;因为代码写入 u.x 然后读取 u.xu.y.a, u.y.bu.y.c,它没有访问最后写入的 union 成员,这是严格未定义的行为。在实践中,它“总是”有效(我还没有听说过它不起作用的系统——它不太可能但在技术上并非不可能存在它不起作用的系统)。

这种布局并不是任何想象中唯一可能的布局。但是,我无法访问演示替代布局的编译器或系统。


在 ISO/IEC 9899:2011 中,§6.7.2.1 结构和 union 说明符部分说:

¶11 An implementation may allocate any addressable storage unit large enough to hold a bitfield. If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined. The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined. The alignment of the addressable storage unit is unspecified.

¶12 A bit-field declaration with no declarator, but only a colon and a width, indicates an unnamed bit-field.126) As a special case, a bit-field structure member with a width of 0 indicates that no further bit-field is to be packed into the unit in which the previous bitfield, if any, was placed.

126) An unnamed bit-field structure member is useful for padding to conform to externally imposed layouts.

问题中结构的轻微变体是:

struct exegesis
{
signed int a:3;
unsigned int :0;
unsigned int b:13;
unsigned int :0;
unsigned int c:1;
};

此结构的大小为 12(在与以前相同的编译器/平台上)。本平台位域的存储单元为4字节,匿名零宽字段开始一个新的存储单元。 a存放在第一个4字节单元的最低3位; b 在第二个 4 字节单元的最低有效 13 位中;和 c 在第三个 4 字节单元的最低有效位。正如标准引述中所述,您也可以拥有大于 0 的匿名位字段。

关于C- 使用位域时结构的大小以及它在内存中的存储方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18284640/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com