结构的C-大小当使用位字段以及它是如何存储在存储器 [英] C- Size of structure when bit field is used and how it is stored in memory

查看:234
本文介绍了结构的C-大小当使用位字段以及它是如何存储在存储器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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个字节?而究竟这些元素存储在内存中?

Why is size 4 bytes here? And how exactly these elements are stored in memory?

推荐答案

位域的几乎每个方面实现定义。即使是纯 INT 位域的符号性是指实施;它可能带符号。字段的布局 - 不管从最显著位去在含有单元(在标准中使用的术语),或者从至少被定义最显著执行至少显著位。最大容许比特字段的大小;当一比特字段被存储在新的单元;所有这些都是实现定义的。

Almost every aspect of bit fields is implementation defined. Even the signedness of a 'plain int' bit field is implementation defined; it may be signed or unsigned. The layout of the fields — whether they go from most significant bit to least significant bit in the containing 'unit' (the term used in the standard) or from least to most significant is implementation defined. The size of the largest permissible bit field; when a bit field is stored in a new unit; all these are implementation defined.

例如,使用GCC 4.8.1的Mac OS X 10.8.4,就可以证明结构位域的质疑与<$布局C $ C> A 占据了3个最小显著位(0-2), b 占据接下来的13位(3-15)和 C 占据未来1位(16):

For example, on Mac OS X 10.8.4 using GCC 4.8.1, it is possible to demonstrate that the struct bitfield in the question is laid out with a occupying the 3 least significant bits (bits 0-2), b occupying the next 13 bits (3-15), and c occupying the next 1 bit (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

The test values are not chosen completely at random. From the test values 0xFEDCBA90 to 0xFECBA97, we can see that the least significant 3 bits contain a. From the test values 0x0000BAA0 and 0x0001BAA0, we can see that the 17th bit (or bit 16) contains c. And from the test values 0x00000008 to 0x0000FFF8, we can see that bits 3-15 contain b.

据但是,必须指出的是,code是在理论上debatably便携;自code写入 UX ,然后读取 UX UYA uyb uyc ,它不是访问最后一次写入到工会,这是成员严格未定义的行为。在实践中,它总是'工作(我没有听说过系统的地方不工作 - 这是不可能的,但不是技术上是不可能的,有一个系统,它不工作)。

It must, however, be pointed out that the code is debatably portable in theory; since the code writes to u.x and then reads u.x and u.y.a, u.y.b and u.y.c, it is not accessing the member of the union last written to, which is strictly undefined behaviour. In practice, it 'always' works (I've not heard of a system where it doesn't work — it is unlikely but not technically impossible that there is a system where it doesn't work).

这布局不是由任何发挥想象力的唯一可能的布局。但是,我没有获得编译器或演示替代布局系统。

This layout is not the only possible layout by any stretch of the imagination. However, I don't have access to compilers or systems that demonstrate alternative layouts.

在ISO / IEC 9899:2011,节§6.7.2.1结构和联合说明符说:

In ISO/IEC 9899:2011, section §6.7.2.1 Structure and union specifiers says:

¶11实现可以分配任何可寻址存储单元,大到足以容纳一个比特。如果有足够的空间保持,紧跟在一个结构的另一位字段位字段须包装到同一单元的相邻比特。如果没有足够的空间仍然存在,不适合一个位字段是否被放入下一个单元或重叠相邻单元是实现定义的。一个单位(高位到低位或低阶到高阶)内的位域的分配顺序是实现定义。可寻址存储单元的取向是不确定的。

¶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位域声明有没有声明,但只有一个冒号和宽度,表示未命名位字段。 126)作为一个特殊的情况下,位字段结构成员与的宽度为0表示没有进一步位字段要被装入其中previous位域,如果有的话,被放置在单元

¶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)未命名的位字段结构成员是非常有用的填充,以符合外界强加的布局。

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

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

A slight variant of the structure in the question is:

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 在第三四字节单元的至少显著位。作为从标准报价提到的,你可以有比0大得有点匿名领域。

This structure has a size of 12 (on the same compiler/platform as before). The storage unit for bit fields on this platform is 4 bytes, so the anonymous zero-width fields start a new storage unit. a is stored in the least significant 3 bits of the first 4-byte unit; b in the least significant 13 bits of the second 4-byte unit; and c in the least significant bit of the third 4-byte unit. As noted in the quote from the standard, you can have anonymous bit fields that are larger than 0 too.

这篇关于结构的C-大小当使用位字段以及它是如何存储在存储器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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