C语言中结构体内存大小问题

include <stdio.h>

typedef struct _tag_LinkList{

struct _tag_LinkList *header; //8

int a; //4

} TLinkList;

int main(int argc, const char * argv[]) {
    // insert code here...

    
    TLinkList List;
    
    printf("ch所占字节的大小为:%lu\n",sizeof (List.a));     // 4
    printf("header所在字节的大小为:%lu\n",sizeof (List.header));    //8
    printf("TLinkList所占字节的大小为:%lu\n",sizeof (List));       //16


    return 0;

}

在xcode7中,运行后,header占8个字节,a占用4个字节,但是整个结构体TlinkList占16个字节。

阅读 4.5k
5 个回答

sizeof 运算符的结果部分地依赖于其作用的类型:

  • 对 char 或者类型为 char 的表达式执行 sizeof 运算,结果得 1;

  • 对引用类型执行 sizeof 运算得到被引用对象所占空间的大小;

  • 对指针执行 sizeof 运算得到指针本身所占空间的大小;

  • 对解引用指针执行 sizeof 运算得到指针指向的对象所占空间的大小,指针不需要有效;

  • 对数组执行 sizeof 运算得到整个数组所占空间的大小(sizeof 不会把数组转换成指针来处理,可以用数组的大小除以单个元素的大小得到数组中元素的个数)。

  • 对 string 对象或 vector 对象执行 sizeof 运算只返回该类型固定部分的大小(24),不会计算对象占用了多少空间;

此外求类的大小时遵循下面规则(只统计与类的实例有关的,只与类型相关的不统计):

  • 类的非静态成员数据的类型大小之和,也就是说静态成员数据不作考虑。

  • 普通成员函数与sizeof无关,调用普通成员函数只需要知道函数的地址即可,而这些地址只与类型相关,与类型的实例无关。

  • 虚函数由于要维护在虚函数表,所以要占据一个指针大小

  • 类的总大小也遵守类似 struct 字节对齐的调整规则

  • 空类的大小为 1(空类型的实例中不包含任何信息,但是声明空类的实例时,必须在内存中占有一定的空间,否则无法使用这些实例。占有空间数由编译器决定,一般是1)。


内存对齐、struct 结构

许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k(通常它为4或8)的倍数,这就是所谓的内存对齐。

每个特定平台上的编译器都有自己的默认“对齐系数”(32位机一般为4,64位机一般为8)。我们可以通过预编译命令#pragma pack(k),k=1,2,4,8,16来改变这个系数,其中k就是需要指定的“对齐系数”;也可以使用#pragma pack()取消自定义字节对齐方式。

struct 或者 union 成员对齐规则如下:

  • 第一个数据成员放在offset为0的地方,每个成员按照对齐系数和自身占用字节数中,二者比较小的那个进行对齐;

  • 在数据成员完成各自对齐以后,struct或者union本身也要进行对齐,对齐将按照对齐系数和struct或者union中最大数据成员长度中比较小的那个进行;

  • 先局部成员对齐,然后再全局对齐。(memory_align.cpp)

此外,值得注意的是,enum 内部是 int 实现的,所以大小为 4。用 typedef 声明指针时,并不为指针分配空间。

字节对齐,编译器为了取值方便,提高效率

新手上路,请多包涵

把 int a放在前面,看看结果有什么不同

编译器在处理结构体的时候要做对齐。

新手上路,请多包涵

对齐呀亲, 要用#pragma pack设置对齐就没事了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进