/* 结构体(联合体)对齐规则 */
#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. CC2431 代码分析②-CC2431狂轰滥炸

    CC2431 code review : CC2431 狂轰滥炸 在上一篇中的最后我们分析到CC2431 开始喊出第一声,这里我们逐步分析从第一声到后面的狂轰滥炸! 上代码 /************ ...

  2. DOCKER上安装HASSIO

    更新源列表命令 sudo apt-get update sudo apt-get upgrade –y This is the list of packages you need to have av ...

  3. C# Json序列化去掉k__BackingField问题的解决方案

    方案一: 如果是WebAPI,可以加入全局设置: GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettin ...

  4. 记一次AngularJs 路由 $stateChangeStart不起作用(细节决定成败)

    var app= angular .module('app', [ 'ngAnimate', 'ngCookies', 'ngResource', 'ngSanitize', 'ngTouch', ' ...

  5. mormot支持TCP/IP

    mormot支持TCP/IP http.sys本来就构建于TCP/IP之上,因此HTTP.SYS是支持TCP/IP连接的. 笔者为此特意写了一个测试DEMO.TCP/IP连接成功. 如果客户端过一段时 ...

  6. SpringMVC整合FastJson:用"最快的json转换工具"替换SpringMVC的默认json转换

    2017年11月23日 09:18:03 阅读数:306 一.环境说明 Windows 10 1709 Spring 4.3.12.RELEASE FastJson 1.2.40 IDEA 2017. ...

  7. Android、iOS、和Web如何做灰度发布?

        主要参考了: https://www.zhihu.com/question/21714205     https://www.zhihu.com/question/28296375  一.概述 ...

  8. 吐槽下mac的打印机设置

    只有第一次使用的时候,会提示密码和用户名验证,但是如果中途修改了密码, 找了半天都找不到,给人一种挫败感. 最后是在:点击作业队列某一作业右边的刷新按钮,才会弹出验证的对话框, 可能,mac当初设计这 ...

  9. python 过滤文本中的标点符号(转)

    网上搜到的大都太复杂,最后找到一个用正则表达式实现的: import re s = "string. With. Punctuation?" # 如果空白符也需要过滤,使用 r'[ ...

  10. curl 模拟表单post文件

    网上查询出来的几乎都是错误的,正确的应该是: $data = array( 'pic'=>new CURLFile($path) // 如果无效可以这样 // 'pic'=>curl_fi ...