C/C++ 结构体成员在内存中的对齐规则(转载)
这几天在看王艳平的《windows 程序设计》,第5章讲解了MFC框架是怎么管理窗口句柄到窗口实例之间的映射,用到了两个类CPlex和CMapPtrToPtr,用于管理内存分配的类(避免因为大量地、频繁地创建窗口对象导致内存碎片的产生)。CMapPtrToPtr类用到了关联结构体
CAssoc,其中有好多对指针类型的转换,感觉对结构体了解不够。特别是成员的对齐方式,跟我猜测的完全不同,花了点时间搞清楚了。在跟朋友一起吃饭还有时间,就顺手写下来,供大家参考:
首先明白几个概念:
1、结构体成员的对齐字节数:可以是n=(1,2,4,8,16);VC编译器默认是8,可以打开工程设置->C/C++->Code Generation,可以看到Struct Member Alignment的值为8;
2、成员所占内存空间的字节数,sizeof(int) = 4,sizeof(short)=2; 设每个成员的内存字节数为:Len
3、成员的偏移字节数,相对于结构体的首地址;
接下来有3条规则:
1、结构体变量的起始地址,也就是第一个成员的地址:为Max(Len) 的整数倍;
2、每个成员的偏移量为:Min(n,Len) 的整数倍;
3、整个结构体占用的空间为:Min( n,Max(Len) ) 的整数倍;
下面看两个例子:
#include <iomanip>
#include <iostream>
using namespace std; #pragma pack(push)
#pragma pack(2) //设置默认对齐字节数
struct MyInfo
{ char age;
int sn;
char sex;
};
#pragma pack(pop) int main(int argc, char* argv[])
{
MyInfo na;
cout<<setw()<<"&na.age:"<<(void*)&na.age<<endl;
cout<<setw()<<"&na.sn:"<<(void*)&na.sn<<endl;
cout<<setw()<<"&na.sex:"<<(void*)&na.sex<<endl;
cout<<setw()<<"sizeof(na):"<<sizeof(na)<<endl;
return ;
}
规则1,2,3均符合:首地址是4的整数倍;第二个成员偏移量为:Min(2,4) = 2的整数倍;总长度为8,是Min( 2,Max(Len) ) = 4的整数倍,第三个成员后有1 Byte的填充。
结果为:
#include <iomanip>
#include <iostream>
using namespace std; #pragma pack(push)
#pragma pack(8) //设置默认对齐字节数
struct MyInfo
{ char age;
int sn;
char sex;
};
#pragma pack(pop) int main(int argc, char* argv[])
{
MyInfo na;
cout<<setw()<<"&na.age:"<<(void*)&na.age<<endl;
cout<<setw()<<"&na.sn:"<<(void*)&na.sn<<endl;
cout<<setw()<<"&na.sex:"<<(void*)&na.sex<<endl;
cout<<setw()<<"sizeof(na):"<<sizeof(na)<<endl;
return ;
}
转载地址:http://www.cnblogs.com/mm220284/archive/2013/09/21/3332181.html
C/C++ 结构体成员在内存中的对齐规则(转载)的更多相关文章
- C/C++ 结构体成员在内存中的对齐规则
这几天在看王艳平的<windows 程序设计>,第5章讲解了MFC框架是怎么管理窗口句柄到窗口实例之间的映射,用到了两个类CPlex和CMapPtrToPtr,用于管理内存分配的类(避免因 ...
- C/C++编程笔记:C语言对齐问题【结构体、栈内存以及位域对齐】
引言 考虑下面的结构体定义: 假设这个结构体的成员在内存中是紧凑排列的,且c1的起始地址是0,则s的地址就是1,c2的地址是3,i的地址是4. 现在,我们编写一个简单的程序: 运行后输出: 为什么会这 ...
- 关于C语言中结构体中的结构体成员导致的字节对齐问题
关于结构体的字节对齐是什么,就不赘述,再此附上一篇文章,介绍字节对齐:http://www.linuxsong.org/2010/09/c-byte-alignment/ 这里的结构体字节对齐的数据类 ...
- C++中的结构体所占内存空间总结
因为结构体有时候需要字节对齐.一般而言,struct 的 sizeof 是所有成员字节对齐后长度相加,而 union 的 sizeof 是取最大的成员长度. 在默认情况下,编译器为每一个变量或数据单元 ...
- C语言中访问结构体成员时用‘.’和‘->’的区别
举个例子,定义了一个叫Student,别名为stu的结构类型,我们声明了一个结构体变量叫stu1,声明了一个结构体指针为stuP. typedef struct Student { char name ...
- C++类成员在内存中的存储及对齐方式
前言:数据对齐的基本理论参见文章:http://www.cnblogs.com/MyBlog-Richard/articles/5993448.html 一.空类的大小 C++中空类的大小是1,这是因 ...
- 指针直接赋值为整型AND利用宏定义求结构体成员偏移量
首先我们要更正一个很熟悉的概念,那就是指针不仅仅是“地址”,指针还有一个很重要的特性,那就是“类型”. 指针初始化时,“=”的右操作数; 除外,该语句表示指针为空): 所以 ; 这样的代码是不允许的. ...
- FFmpeg源代码简单分析:结构体成员管理系统-AVOption
===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...
- FFmpeg源代码简单分析:结构体成员管理系统-AVClass
===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...
随机推荐
- golang之pkg(包)
一.概述 Golang拥有超过100个标准包(可用go list std |wc -l查看) 任何包系统设计的目的都是简化大型程序的设计和维护工作,通过将一组相关的特性放进一个独立的模块以便于理解和更 ...
- C#核编之系统数据类型和相应的C#关键字
和任何编程语言一样,C#定义了一组用于表示局部变量.成员变量.返回值以及输入参数的基本数据类型.然而,与其他编程语言不同的是,这些关键字不只是编译器能识别的标记.C#关键字其实是System命名空间中 ...
- IBATIS处理typeHandler类容易范的SQLException总结
1. java.sql.SQLException: 无效的列类型 原因: A. ibatis的IN,OUT参数.或者typeHandler类中传入的参数值数据类型与Oracle自定义对象中的属性值的数 ...
- Java中 map.values转换为list或者string[]
@Test public void testMap2List() throws Exception{ Map<String, String> map = new HashMap<St ...
- ZOJ 1530 - Find The Multiple
Given a positive integer n, write a program to find out a nonzero multiple m of n whose decimal repr ...
- DOS 根据用户输入执行指令判断IF
@echo off set /p op="输入指令:" if "%op%" == "1" ( echo 你输入了指令1 ) if " ...
- XML字符串转化json
public static String XMLTOJSON(String XMLContent,String tag) { XMLSerializer xmlSerializer = new XM ...
- JavaScript中的Math.ceil()、Math.round()、Math.floor()
1. Math.ceil():向上取整(指取大于该浮点数的最小整数) 2. Math.round():四舍五入取整(注意:当该浮点数距离两端整数一样时,取较大的那个整数,如Math.round(-1. ...
- 浏览器的重绘repaints与重排reflows深入分析
重绘是一个元素外观的改变所触发的浏览器行为,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观,接下来将详细介绍,需要了解的朋友可以参考下: 在项目的交互或视觉评审中,前端同学常常会对一些交互效果质 ...
- 在Linux手动把文件转码的方法,防止乱码出现
iconv -f utf-8 -t gb2312 report.html > report_test.html