C-struct-位段、无名字段以及填充字段

C语言 码拜 9年前 (2016-05-15) 1949次浏览
#include <stdio.h>
/*
 *结构体中允许存在位段、无名字段以及字对齐所需的填充字段。
 *位段的类型必须是int, unsigned int或signed int(或加上限定符)。
 *至于int位段的值可不可以取负值取决于编译器。
 *在使用位段时,要考虑字对齐的问题。系统默认的是4字节对齐。
 *
 */
//4Bytes
struct S1
{
    unsigned int inactive : 1;    // 分配1个bit
};
//4Bytes
struct S2
{
    unsigned int inactive : 1;    // 分配1个bit
    short id;                    // 与inactive共用4个Bytes
};
//2Bytes
struct S3
{
    short id;
};
//4Bytes
struct S4
{
    unsigned int inactive : 1;        // 分配1个bit
    short id;                        // 与inactive共用4个Bytes
    unsigned int : 0;                // 填充到下一个字边界
};
//8Bytes
struct S5
{
    unsigned int inactive : 1;        // 分配1个bit
    unsigned int : 0;                // 填充到下一个字边界
    short id;                        // 占用下1个新的4个Bytes(字对齐)
};
//8Bytes
struct S6
{
    unsigned int inactive : 1;        // 分配1个bit
    unsigned int : 0;                // 填充到下一个字边界
    unsigned int new_Bytes : 1;        // 占用新的4个Bytes
    unsigned int new_Bytes1 : 1;    // 与new_Bytes共用1个Bytes
    short id;                        //  与new_BYtes,new_Bytes1共用1个Bytes
};
//12Bytes
struct S7
{
    unsigned int inactive : 1;        // 分配1个bit
    unsigned int : 0;                // 填充到下一个字边界
    unsigned int new_Bytes : 1;        // 占用新的4个Bytes
    short id;                        //  与new_BYtes共用1个Bytes
    unsigned int new_Bytes1 : 1;    // 占用1个新的4个Bytes
};
int main()
{
    printf("short        = %d    Bytes\n", sizeof(short));
    printf("unsigned int    = %d    Bytes\n", sizeof(unsigned int));
    printf("S1        = %d    Bytes\n", sizeof(struct S1));
    printf("S2        = %d    Bytes\n", sizeof(struct S2));
    printf("S3        = %d    Bytes\n", sizeof(struct S3));
    printf("S4        = %d    Bytes\n", sizeof(struct S4));
    printf("S5        = %d    Bytes\n", sizeof(struct S5));
    printf("S6        = %d    Bytes\n", sizeof(struct S6));
    printf("S7        = %d    Bytes\n", sizeof(struct S7));
    return 0;
}
e:\Workspace\Others\C\Struct>g++ struct.c -o struct
e:\Workspace\Others\C\Struct>struct
short           = 2     Bytes
unsigned int    = 4     Bytes
S1              = 4     Bytes
S2              = 4     Bytes
S3              = 2     Bytes
S4              = 4     Bytes
S5              = 8     Bytes
S6              = 8     Bytes
S7              = 12    Bytes
解决方案

30

仅供参考:

#include <stdio.h>
#pragma pack(push,1)
union U {
    unsigned char byte;
    struct BF {
        unsigned int b0:1;//a
        unsigned int b1:1;//b
        unsigned int b2:1;//c
    } bf;
} u;
#pragma pack(pop)
unsigned char bt;
int a,b,c;
int main() {
    for (bt=0;bt<8;bt++) {
        u.byte=(unsigned char)bt;
        a=u.bf.b0;
        b=u.bf.b1;
        c=u.bf.b2;
        printf("byte 0x%02x -- c:%d b:%d a:%d\n",bt,c,b,a);
    }
    for (c=0;c<2;c++)
    for (b=0;b<2;b++)
    for (a=0;a<2;a++) {
        u.bf.b0=a;
        u.bf.b1=b;
        u.bf.b2=c;
        bt=u.byte;
        printf("c:%d b:%d a:%d -- byte 0x%02x\n",c,b,a,bt);
    }
    return 0;
}
//byte 0x00 -- c:0 b:0 a:0
//byte 0x01 -- c:0 b:0 a:1
//byte 0x02 -- c:0 b:1 a:0
//byte 0x03 -- c:0 b:1 a:1
//byte 0x04 -- c:1 b:0 a:0
//byte 0x05 -- c:1 b:0 a:1
//byte 0x06 -- c:1 b:1 a:0
//byte 0x07 -- c:1 b:1 a:1
//c:0 b:0 a:0 -- byte 0x00
//c:0 b:0 a:1 -- byte 0x01
//c:0 b:1 a:0 -- byte 0x02
//c:0 b:1 a:1 -- byte 0x03
//c:1 b:0 a:0 -- byte 0x04
//c:1 b:0 a:1 -- byte 0x05
//c:1 b:1 a:0 -- byte 0x06
//c:1 b:1 a:1 -- byte 0x07

再供参考:

#include <stdio.h>
#define field_offset(s,f) (int)(&(((struct s *)(0))->f))
struct AD  { int a; char b[13]; double c;};
#pragma pack(push)
#pragma pack(1)
struct A1  { int a; char b[13]; double c;};
#pragma pack(2)
struct A2  { int a; char b[13]; double c;};
#pragma pack(4)
struct A4  { int a; char b[13]; double c;};
#pragma pack(8)
struct A8  { int a; char b[13]; double c;};
#pragma pack(16)
struct A16 { int a; char b[13]; double c;};
#pragma pack(pop)
int main() {
    printf("AD.a %d\n",field_offset(AD,a));
    printf("AD.b %d\n",field_offset(AD,b));
    printf("AD.c %d\n",field_offset(AD,c));
    printf("AD sizeof %d\n", sizeof(AD));
    printf("\n");
    printf("A1.a %d\n",field_offset(A1,a));
    printf("A1.b %d\n",field_offset(A1,b));
    printf("A1.c %d\n",field_offset(A1,c));
    printf("A1 sizeof %d\n", sizeof(A1));
    printf("\n");
    printf("A2.a %d\n",field_offset(A2,a));
    printf("A2.b %d\n",field_offset(A2,b));
    printf("A2.c %d\n",field_offset(A2,c));
    printf("A2 sizeof %d\n", sizeof(A2));
    printf("\n");
    printf("A4.a %d\n",field_offset(A4,a));
    printf("A4.b %d\n",field_offset(A4,b));
    printf("A4.c %d\n",field_offset(A4,c));
    printf("A4 sizeof %d\n", sizeof(A4));
    printf("\n");
    printf("A8.a %d\n",field_offset(A8,a));
    printf("A8.b %d\n",field_offset(A8,b));
    printf("A8.c %d\n",field_offset(A8,c));
    printf("A8 sizeof %d\n", sizeof(A8));
    printf("\n");
    printf("A16.a %d\n",field_offset(A16,a));
    printf("A16.b %d\n",field_offset(A16,b));
    printf("A16.c %d\n",field_offset(A16,c));
    printf("A16 sizeof %d\n", sizeof(A16));
    printf("\n");
    return 0;
}
//AD.a 0
//AD.b 4
//AD.c 24
//AD sizeof 32
//
//A1.a 0
//A1.b 4
//A1.c 17
//A1 sizeof 25
//
//A2.a 0
//A2.b 4
//A2.c 18
//A2 sizeof 26
//
//A4.a 0
//A4.b 4
//A4.c 20
//A4 sizeof 28
//
//A8.a 0
//A8.b 4
//A8.c 24
//A8 sizeof 32
//
//A16.a 0
//A16.b 4
//A16.c 24
//A16 sizeof 32
//
//

不要迷信书、考题、老师、回帖;
要迷信CPU、编译器、调试器、运行结果。
并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。
任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实!

10

位段的位顺序,由实现决定
也就说说
位段中,字节顺序位顺序。都是不确定的,由具体实现觉得。

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明C-struct-位段、无名字段以及填充字段
喜欢 (0)
[1034331897@qq.com]
分享 (0)