/* 结构体(联合体)对齐规则 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /*
* 原则1、第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储)。 * 原则2、结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最宽基本类型大小的整数倍地址开始存储。 *原则3、结构体的总大小为结构体最宽基本类型成员(成员可以是基本类型,也可以是结构体)大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节 *最宽基本类型的概念,所谓基本类型是指像char、short、int、float、double这样的内置数据类型。 */ struct Data1
{
int c;
char a;
char b;
}; /*
struct Data1分析
分析对齐数
对齐数的值是 结构体中最宽基本类型成员
struct Data1最宽类型是int,占4个字节大小,所以对齐数的值是4 根据原则1(第一个数据成员放在offset为0的地方),成员属性c从offset为0的位置开始,成员属性c大小是4个字节,成员属性c从offset为0的位置开始存储,占据4个字节大小 成员属性a从offset为4的位置开始,根据原则1(以后每个数据成员存储的起始位置要从该成员大小的整数倍开始) ,现在offset是4,是1的整数倍
所以成员属性a从offset为4的位置开始存储,占据1个字节大小 成员属性b从offset为5的位置开始,根据原则1(以后每个数据成员存储的起始位置要从该成员大小的整数倍开始) ,现在offset是5,是1的整数倍
所以成员属性b从offset为5的位置开始存储,占据1个字节大小 现在struct Data1一共占据6个字节大小的空间,根据原则3(必须是其内部最大成员的整数倍),struct Data1最宽基本类型是int,占4个字节大小
因此结构体的总大小必须是4的倍数,6不是4的倍数,补齐2个字节,变成8个字节
结论:struct Data1 大小是8个字节 */ struct Data2
{
char a;
int c;
char b;
}; /*
struct Data2分析
分析对齐数
struct Data2最宽类型是int,占4个字节大小,所以对齐数的值是4 根据原则1(第一个数据成员放在offset为0的地方),成员属性a从offset为0的位置开始,成员属性a大小是1个字节,成员属性a从offset为0的位置开始存储,占据1个字节大小 成员属性c是int类型,根据原则1(以后每个数据成员存储的起始位置要从该成员大小的整数倍开始),现在offset是1,1不是4的整数倍
编译器填充3个字节,现在offset为4 , 4是int的整数倍,成员属性c从offset为4的位置开始存储,占据4个字节大小 成员属性b从offset为8的位置开始,根据原则1(以后每个数据成员存储的起始位置要从该成员大小的整数倍开始) ,现在offset是8,是1的整数倍
所以成员属性b从offset为8的位置开始存储,占据1个字节大小 现在struct Data2一共占据9个字节大小的空间,根据原则3(必须是其内部最大成员的整数倍),struct Data2最宽基本类型是int,占4个字节大小
因此结构体的总大小必须是4的倍数,9不是4的倍数,补齐3个字节,变成12个字节
结论:struct Data1 大小是12个字节 */ struct Data3
{
char a;
short b;
double c;
}; /*
struct Data3分析
分析对齐数
struct Data3最宽类型是double,占8个字节大小,所以对齐数的值是8 根据原则1(第一个数据成员放在offset为0的地方),成员属性a从offset为0的位置开始,成员属性a大小是1个字节,成员属性a从offset为0的位置开始存储,占据1个字节大小 成员属性b从offset为1的位置开始,根据原则1(以后每个数据成员存储的起始位置要从该成员大小的整数倍开始) ,现在offset是1,不是short的整数倍
编译器填充1个字节,现在offset为2 , 2是short的整数倍,成员属性b从offset为2的位置开始存储,占据2个字节大小 成员属性c从offset为4的位置开始,根据原则1(以后每个数据成员存储的起始位置要从该成员大小的整数倍开始) ,现在offset是4,不是double的整数倍
编译器填充4个字节,现在offset为8 , 8是double的整数倍,成员属性c从offset为8的位置开始存储,占据8个字节大小 现在struct Data3一共占据16个字节大小的空间,根据原则3(必须是其内部最大成员的整数倍),struct Data3最宽基本类型是double,占8个字节大小
因此结构体的总大小必须是8的倍数,16是8的倍数,不用填充字节
结论:struct Data3 大小是16个字节 */ struct Data4
{
short a;
char b;
double c;
char d[];
}; /*
struct Data4分析
分析对齐数
struct Data3最宽类型是double,占8个字节大小,所以对齐数的值是8
char d[5]并非基本类型 根据原则1(第一个数据成员放在offset为0的地方),成员属性a从offset为0的位置开始,成员属性a大小是2个字节,成员属性a从offset为0的位置开始存储,占据2个字节大小 成员属性b从offset为2的位置开始,根据原则1(以后每个数据成员存储的起始位置要从该成员大小的整数倍开始) ,现在offset是2,是1的整数倍
成员属性b从offset为2的位置开始存储,占据1个字节大小 成员属性c从offset为3的位置开始,根据原则1(以后每个数据成员存储的起始位置要从该成员大小的整数倍开始) ,现在offset是3,不是double的整数倍
编译器填充5个字节,现在offset为8 , 8是double的整数倍,成员属性c从offset为8的位置开始存储,占据8个字节大小 成员属性d从offset为16的位置开始,根据原则1(以后每个数据成员存储的起始位置要从该成员大小的整数倍开始) ,现在offset是16,是char的整数倍
成员属性d从offset为16的位置开始存储,占据1个字节大小 现在struct Data4一共占据17个字节大小的空间,根据原则3(必须是其内部最大成员的整数倍),struct Data3最宽基本类型是double,占8个字节大小
因此结构体的总大小必须是8的倍数,17不是8的倍数,需要填充7个字节
结论:struct Data4 大小是24个字节 */ struct Data5
{
short a;
struct Data4 b;
}; /*
struct Data5分析
分析对齐数
根据原则2, struct Data4最宽类型是double 占8个字节大小,而struct Data5成员a占2个字节,所以对齐数的值是8 根据原则1(第一个数据成员放在offset为0的地方),成员属性a从offset为0的位置开始,成员属性a大小是2个字节,成员属性a从offset为0的位置开始存储,占据2个字节大小 成员属性b从offset为2的位置开始,根据原则2(结构体成员要从其内部最大元素大小的整数倍地址开始存储) ,现在offset是2,不是double的整数倍
编译器填充6个字节,现在offset为8 , 8是double的整数倍,成员属性b从offset为8的位置开始存储,占据24个字节大小 现在struct Data5一共占据32个字节大小的空间,根据原则3(必须是其内部最大成员的整数倍),struct Data5最宽基本类型是double,占8个字节大小
因此结构体的总大小必须是8的倍数,32是8的倍数,不需要填充字节
结论:struct Data5 大小是32个字节 */ struct Data6
{
double a;
struct Data1 b;
}; /*
struct Data6分析
分析对齐数
根据原则2, struct Data1最宽类型是int 占4个字节大小,而struct Data5成员a 占8个字节,所以对齐数的值是8 根据原则1(第一个数据成员放在offset为0的地方),成员属性a从offset为0的位置开始,成员属性a大小是8个字节,成员属性a从offset为0的位置开始存储,占据8个字节大小 成员属性b从offset为8的位置开始,根据原则2(结构体成员要从其内部最大元素大小的整数倍地址开始存储) ,现在offset是8 ,是 int 的整数倍
成员属性b从offset为8的位置开始存储,占据8个字节大小 现在struct Data6一共占据16个字节大小的空间,根据原则3(必须是其内部最大成员的整数倍),struct Data6最宽基本类型是double,占8个字节大小
因此结构体的总大小必须是8的倍数,16是8的倍数,不需要填充字节
结论:struct Data6 大小是16个字节 */ void test()
{
printf("----struct size---1-[%d]------\n", sizeof(struct Data1)); //
printf("----struct size--2--[%d]------\n", sizeof(struct Data2)); //
printf("----struct size--3--[%d]------\n", sizeof(struct Data3)); //
printf("----struct size--4--[%d]------\n", sizeof(struct Data4)); //
printf("----struct size--5--[%d]------\n", sizeof(struct Data5)); //
printf("----struct size--6--[%d]------\n", sizeof(struct Data6)); //
} int main()
{
test();
printf("-----ok------\n");
getchar();
return ;
}

C语言 结构体(联合体)对齐规则的更多相关文章

  1. [置顶] 什么是C语言结构体字节对齐,为什么要对齐?

    一.概念 对齐跟数据在内存中的位置有关.如果一个变量的内存地址正好位于它长度的整数倍,他就被称做自然对齐.比如在32位cpu下,假设一个整型变量的地址为0x00000004,那它就是自然对齐的.   ...

  2. C语言结构体的对齐原则

    Q:关于结构体的对齐,到底遵循什么原则?A:首先先不讨论结构体按多少字节对齐,先看看只以1字节对齐的情况: #include <stdio.h> #include <string.h ...

  3. C语言 结构体字节对齐问题

    摘选自这位大神的博客 方法一: 结构体在内存中分配一块连续的内存,但结构体内的变量并不一定是连续存放的,这涉及到内存对齐. 原则1  数据成员对齐规则:结构(struct或联合union)的数据成员, ...

  4. c中结构体边界对齐

    原则1.普通数据成员对齐规则:第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储). 原则2 ...

  5. C语言结构体对齐

    1.结构体变量中的元素如何访问? (1)数组中元素的访问方式:表面上有2种方式(数组下标方式和指针方式):实质上都是指针方式访问.(2)结构体变量中的元素访问方式:只有一种,用.或者->的方式来 ...

  6. 解析C语言结构体对齐(内存对齐问题)

    C语言结构体对齐也是老生常谈的话题了.基本上是面试题的必考题.内容虽然很基础,但一不小心就会弄错.写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的 ...

  7. C语言 结构体的内存对齐问题与位域

    http://blog.csdn.net/xing_hao/article/details/6678048 一.内存对齐 许多计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地 ...

  8. C语言结构体的字节对齐原则

    为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据 ...

  9. C语言基础(19)-结构体,联合体,枚举和typedef

    一.结构体 1.1 结构体struct定义及初始化 #include <stdio.h> // 这个头文件在系统目录下 #include <stdlib.h> // 使用了sy ...

随机推荐

  1. 1171 Big Event in HDU 01背包

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1171 题意:把商品分成两半,如不能均分,尽可能的让两个数相接近.输出结果:两个数字a,b且a>=b. ...

  2. MySQL(四)

    分组 按照字段分组,表示此字段相同的数据会被放到一个组中 分组后,只能查询出相同的数据列,对于有差异的数据列无法出现在结果集中 可以对分组后的数据进行统计,做聚合运算 语法: select 列1,列2 ...

  3. flask内容学习之蓝图以及单元测试

    蓝图的概念: 简单来说,蓝图是一个存储操作方法的容器.这些操作在这个蓝图被注册到一个应用之后就可以被调用.Flask可以通过蓝图来制止URL以及处理请求.Flask使用蓝图来让应用实现模块化,在Fla ...

  4. oracle 10g 11g 12c区别

    oracle 10g 11g 12c区别

  5. angular学习笔记(3)- MVC

    angular1学习笔记(3)- MVC --- MVC终极目标 - 模块化和复用 AngularJs的MVC是借助于$scope实现的!!! 神奇的$scope: 1.$scope是一个POJO(P ...

  6. JSAP101

    JSAP101 1.DOM 1)文档对象模型 文档:把一个Html文件看成一个文档,所以把这个文档看成一个对象.XML文件也可以看成一个文件.XML侧重于存储数据,html主要以展示为主.一个页面就是 ...

  7. Linux下修改环境变量,不小心改错,找不到命令解决办法

    PATH改错了找不到命令 解决方法: 重新定义PATH export PATH=/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/us ...

  8. centos7安装redis设置开机启动

    1. 首先下载redis源码,并使用tar进行解压缩 wget http://download.redis.io/releases/redis-4.0.8.tar.gztar xvzf redis-4 ...

  9. Netty 中ChannelOption的含义以及使用的场景

    Netty 中ChannelOption的含义以及使用的场景 转自:http://www.cnblogs.com/googlemeoften/p/6082785.html 1.ChannelOptio ...

  10. Delphi10.2 DPR文件

    通过选择[Project | View Source],可以看到DPR文件的基本面貌,操作如下: 默认的 Delphi 项目文件的内容如下: program Project1; {关键字 progra ...