关于C语言中结构体中的结构体成员导致的字节对齐问题
关于结构体的字节对齐是什么,就不赘述,再此附上一篇文章,介绍字节对齐:http://www.linuxsong.org/2010/09/c-byte-alignment/
这里的结构体字节对齐的数据类型都是基本数据类型,如果结构体的定义中含有结构体成员呢?
网上有很多人写博客谈到这个问题,都认为该结构体成员应该被看做一个整体,按照整体的字节数来进行字节对齐,选择首地址。但是经过测试,这种说法是不对的。
struct s1{
char c1;
char c2;
char c3;
char c4;
};
struct s2{
char a;
struct s1 s;
};
对于上述代码,显然sizeof(struct s1) = 4。如果将struct s1看做整体,来进行字节对齐的话,sizeof(struct s2)应该是等于8。但是该段代码在gcc和VS2010下测试的结果都是5。
所以,s2的内存布局如下
s2 : char | char char char char |
s的首地址并非为4,而是char类型长度的整数倍
同样,对于结构体:
struct S1
{
char a;
short b;
}; struct S2
{
char a;
struct S1 s;
};
上述代码中,sizeof(struct S1) = 4,而sizeof(struct S2) = 6。
S2的内存布局是:
S2 : char **** | char **** short short
s的首地址并非为4,而是short类型长度的整数倍,结构体S2的长度并非结构体S1长度的整数倍,而是short类型长度的整数倍
相对的,我们可以看一下结构体:
struct S
{
char a;
char b;
short c;
};
sizeof(S) = 4。
其内存布局为:
S : char char short short
对比S2和S,我们看到,S2中的s结构体成员确实是仍按它作为S1结构体的整体(占用4个字节)来布局的。
那么我们可以得出这情形下的字节对齐问题的结论:
1)结构体中的结构体成员,是按照原结构体的内存布局在新结构体中进行布局的;
2)结构体中的结构体成员,其内存首地址为该成员中最长数据类型的整数倍;
3)结构体的整体长度与其中的结构体成员无关,而是整个结构体(包括结构体成员内部)中的最长数据类型的整数倍。
得出结论后,我们回到处理器本身,来探讨一下编译器之所以这么处理的原因。
从CPU结构角度看内存对齐有一篇比较易懂的文章:
http://hi.baidu.com/maikeai/item/4976f24cc0f905d3c1a592a0
从该文章中,我们可以知道,之所以需要内存对齐,是CPU为了读取数据时减少读取存储器的次数,提高效率。
对于32位的CPU,一次最多读入双字的32位数据,而对于超过32位的数据,在32位的计算机上,就必须多次读取存储器,这与是否字节对齐无关。
我们可以看到,字节对齐,其实实质上是在拿存储器的空间,换CPU的时间。
所以,对于C语言内置的数据类型,可以很好地通过内存对齐来节省时间,同时其浪费的存储器空间也是可控的。
但是,对于结构体成员来说,因为它的长度是不可控的,所以如果强行按整体内存对齐,首先可能因为长度过长,即使内存对齐需要的存储器读取次数也很多,导致优化的时间不明显,另外,也可能导致浪费的存储器空间太大。所以,最简单的平衡空间和时间的方法,就是按照该结构体成员中最长数据类型来进行字节对齐,这样最有可能减少存储器读取次数,也使浪费的存储器空间可控。
完
关于C语言中结构体中的结构体成员导致的字节对齐问题的更多相关文章
- C语言提高 (5) 第五天 结构体,结构体对齐 文件
1昨日回顾 2作业讲解 3 结构体的基本定义 //1 struct teacher { int id; char name[64]; }; struct teacher t5 = { 5, " ...
- C语言中的字节对齐以及其相关处理
首先,我们来了解下一些基本原理: 一.什么是字节对齐一个基本类型的变量在内存中占用n个字节,则该变量的起始地址必须能够被n整除,即: 存放起始地址 % n = 0,那么,就成该变量是字节对齐的;对于结 ...
- [置顶]
什么是C语言结构体字节对齐,为什么要对齐?
一.概念 对齐跟数据在内存中的位置有关.如果一个变量的内存地址正好位于它长度的整数倍,他就被称做自然对齐.比如在32位cpu下,假设一个整型变量的地址为0x00000004,那它就是自然对齐的. ...
- C语言结构体变量字节对齐问题总结
结构体字节对齐 在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题.从理论上讲,对于任何 变量的访问都可以从任何地址开始访问,但 ...
- C语言中的字节对齐
下面这个篇博客讲解很好 http://blog.csdn.net/meegomeego/article/details/9393783 总的来看分三类: 1. 不加 #pragma pack(n)伪指 ...
- stm32中使用#pragma pack(非常有用的字节对齐用法说明)
#pragma pack(4) //按4字节对齐,但实际上由于结构体中单个成员的最大占用字节数为2字节,因此实际还是按2字节对齐 typedef struct { char buf[3];//bu ...
- C/C++ 结构体字节对齐
在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题.从理论上讲,对于任何 变量的访问都可以从任何地址开始访问,但是事实上不是如此 ...
- ACE的CDR中的字节对齐问题
大家应该都知道计算机中间都有字节对齐问题.CPU访问内存的时候,如果从特定的地址开始访问一般可以加快速度,比如在32位机器上,如果一个32位的整数被放在能被32模除等于0的地址上,只需要访问一次,而如 ...
- C语言字节对齐问题详解
引言 考虑下面的结构体定义: typedef struct{ char c1; short s; char c2; int i; }T_FOO; 假设这个结构体的成员在内存中是紧凑排列的,且c1的起始 ...
随机推荐
- 【.Net】从.NET平台调用Win32 API
小序 Win32 API可以直接控制Microsoft Windows的核心,因为API(Application Programming Interface)本来就是微软留给我们直接控制 ...
- 前端开发的常用js库
验证: jQuery formValidator,Validform; 提示框: artDialog, lhgDialog,jBox,jQuery textbox plugin 文件批量上传:uplo ...
- C++语言学习——LRJ入门经典笔记
1.scanf的输入格式,空格.TAB和回车符都是无关紧要,所以按Enter键并不意味着输入结束. 告诉程序输入结束的方式: 在windows下,输入完毕后先按Enter键,再按Ctrl+Z键,最后再 ...
- 万事开头难——Cocos2d-x学习历程(一)
万事开头难,不知该从哪里开始,不过既然要学习一样新东西,那就从了解它开始吧... Cocos2d-x是一个通用平面游戏引擎,基于一个同样十分著名的游戏引擎Cocos2d-iPhone设计,Cocos2 ...
- n多边形面积
“ 改革春风吹满地,不会AC没关系;实在不行回老家,还有一亩三分地.谢谢!(乐队奏乐)” 话说部分学生心态极好,每天就知道游戏,这次考试如此简单的题目,也是云里雾里,而且,还竟然来这么几句打油诗.好呀 ...
- jquery 实现横向滑动自动切换源码(同时显示多张图片)
html代码: <!doctype html> <html lang="en"> <head> <meta charset="U ...
- PHP Version之PHP5.2.x到5.3.x
不向下兼容的变化 1. 在5.3的所有绑定扩展中应用了新的内部参数解析API,当给函数传递不兼容的参数时将返回NULL,但有些例外,比如函数get_class()在出现错误时返回FALSE 2. ...
- 随学随用的python-note
Python笔记---------------[] 列表解析 >>> [(x,y) for x in range(3) for y in range(5)] [(0, 0), (0, ...
- HCE:Host-based Card Emulation基于Android设备的卡片模拟器
HCE技术支持提供了一个软实现SE的通路,Service实现的方式很多,可以使用文件,使用网络,甚至连接真正的SE.支持HCE的测试手机:目前可以确定使用了NXP PN547作为CLF的NFC手机已经 ...
- Linux进程间通信——使用信号量
这篇文章将讲述别一种进程间通信的机制——信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信——使用信号.下面 ...