结构体大小的计算方法

类型大小

32位编译器:32位系统下指针占用4字节

  char:1个字节

  char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节)

  shortint :2个字节

  int:  4个字节

  unsigned int: 4个字节

  float:  4个字节

  double:   8个字节

  long:   4个字节

  long long:  8个字节

  unsigned long: 4个字节

64位编译器:64位系统下指针占用8字节

  char:1个字节

  char*(即指针变量): 8个字节

  short int :2个字节

  int:  4个字节

  unsigned int: 4个字节

  float:  4个字节

  double:   8个字节

  long:   8个字节

  long long:  8个字节

  unsigned long: 8个字节

结构体大小计算方法

① 计算有效对齐值 V = min(n, maxMemberSize);
其中n为指定的编译器选项,即#pragma pack(n)。如果没有指定,gcc在32位系统上默认值是4,在64位系统上默认值是8;
maxMemberSize为结构体中最大的基本类型成员变量的大小;

② 计算offset偏移量 offset = min(V, memberSize);
其中memberSize为当前成员的大小;如果当前成员也是结构体,那么此时memberSize按照该子结构体中最大基本类型成员变量的大小;

③ 结构体的总大小必须为V的整数倍,即totalSize = N*V

实例验证

例1

#include <stdio.h>

struct object {
        char a;
};

struct object1 {
        char a;
        short b;
};

struct object2 {
        char a;
        int b;
};

int main(void) {
        printf("size of struct object is %u\n", sizeof(struct object));
        printf("size of struct object1 is %u\n", sizeof(struct object1));
        printf("size of struct object2 is %u\n", sizeof(struct object2));
        
        return 0;
}

在32位上和64位上的运行结果分别为:
在这里插入图片描述

例2

struct example1 {
    short a;
    long b;
};

struct example2 {
    char c;
    struct example1 obj1;
    short e;    
};

int main(void) {
		struct example2 obj2;
        printf("size of struct example1 is %u\n", sizeof(struct example1));
        printf("size of struct example2 is %u\n", sizeof(struct example2));
        unsigned int offset = (unsigned int)(&obj2.obj1) - (unsigned int)(&obj2);
        printf("offset is %u\n", offset);
        
        return 0;
}

在32位上和64位上的运行结果分别为:
在这里插入图片描述

GCC更改对齐选项

可以通过使用gcc中的__attribute__选项来设置对齐大小。

  1. _attribute_((packed))
    用来让所修饰的结构体在编译的时候不进行对齐优化,按照实际占用的字节数来使用。使用该项修饰后,该结构体后续都不会参与对齐。
  2. _attribute_((aligned(n)))
    让所修饰的结构体成员按照n字节对齐。32位平台上gcc默认按4字节对齐;64位平台gcc默认按照8字节对齐。

代码验证

#include <stdio.h>
#pragma pack(8)
struct example1 {
    short a;
    long b;
}__attribute__((packed));

//因为example1被__attribute__((packed))修饰了,所以在example2中则不再参与对齐操作
//所以V=min(4, 2) = 2
//offset = min(V, memberSize)
//0	c
//1 obj1
//6 obj1
//7 
//8	e
//9 e
//totalSize = 10
struct example2 {
    char c;
    struct example1 obj1;
    short e;
};
#pragma pack()
int main(void) {
        struct example2 obj2;
        printf("size of struct example1 is %u\n", sizeof(struct example1));
        printf("size of struct example2 is %u\n", sizeof(struct example2));
        unsigned int offset = (unsigned int)(&obj2.obj1) - (unsigned int)(&obj2);
        printf("offset is %u\n", offset);

        return 0;
}

在32位平台上运行结果为:

size of struct example1 is 6
size of struct example2 is 10
offset is 1

发布了26 篇原创文章 · 获赞 2 · 访问量 1077

猜你喜欢

转载自blog.csdn.net/BakerTheGreat/article/details/104234055