C++结构体字节对齐
转自:http://www.cnblogs.com/JensenCat/p/4770171.html
这里是头文件结构的定义:
一个非字节对齐结构体_tagTest2
一个字节对齐_tagTest3
(使用#pragma pack(push,1)来使字节以1个来对齐 , 使用#pragma pack(pop)来还原默认)
- #pragma once
- struct _tagTest1
- {
- };
- //非字节对齐的结果
- struct _tagTest2
- {
- int n1;
- char ch1;
- float f1;
- char szName[];
- _tagTest1* pTag;
- };
- #pragma pack(push,1)
- //_tagTest3和2是一样的结构,字节对齐后的结果
- struct _tagTest3
- {
- int n1;
- char ch1;
- float f1;
- char szName[];
- _tagTest1* pTag;
- };
- #pragma pack(pop)
这里是实验代码:注释处写了分析,结果也入分析所料
- #include "msgdef.h"
- #include <Windows.h>
- #include <iostream>
- using namespace std;
- void main()
- {
- /*
- 非字节对齐下,当前最大的空间是4个字节,所有结构都会向4个字节对齐...
- int n1; 4
- char ch1; 4 注解:1不是4的倍数..将扩张到4
- float f1; 4
- char szName[21]; 24 注解:21不是4的倍数..将扩张到24
- _tagTest1* pTag; 4
- 总和为:40
- */
- _tagTest2 k2;
- cout<<"size of _tagTest2: "<<sizeof(k2)<<endl;
- //看看内存模型
- k2.n1 = ;
- k2.ch1 = ;
- k2.f1 = 1.0f;
- memset(k2.szName , , sizeof(k2.szName));
- k2.pTag = (_tagTest1*)&k2.n1; //此处测试用,别纠结
- /*
- 字节对齐下,
- int n1; 4
- char ch1; 1
- float f1; 4
- char szName[21]; 21
- _tagTest1* pTag; 4
- 总和为:34
- */
- _tagTest3 k3;
- cout<<"size of _tagTest3: "<<sizeof(k3)<<endl;
- //看看内存模型
- k3.n1 = ;
- k3.ch1 = ;
- k3.f1 = 1.0f;
- memset(k3.szName , , sizeof(k3.szName));
- k3.pTag = (_tagTest1*)&k3.n1; //此处测试用,别纠结
- system("pause");
- }
实验结果输出:如分析所说的一样
这时候问题来了,那么字节不对齐时在内存是怎样的呢...下面是字节不对齐时的内存截图
下面的顺序清楚的对应,其中字节对齐的空位在内存里面补了cc,这个为什么本人没有深究,其他变量一目了然了,
至于浮点数的内存模型为什么是这样,可以度娘一下,很多人分析了浮点数float的内存模型。
----------------------------------------------------------------------------------------------------------------------------
----------------------------邪恶的分割线------------------------------------------------------------------------------------
2.0版本:
鉴于上面有些地方不够清晰...现在再列出几个例子...例子来自网上摘下...
1.在不对齐的情况下,拥有相同变量的结构最后得出的size也是不一样的..
- //定义两个结构,下面描述一下内存存放地址
- struct A
- {
- //假设内存地址从0开始...
- int a; //0-3
- char b; //4
- short c;//6-7
- }
- //由于0-7的相加的结果为8...为自对齐4的倍数...
- //所以结果:sizeof(A) = 8
- //
- struct B
- {
- //假设内存地址从0开始...
- char a;//0
- int b; //4-7
- short c;//8-10
- }
- //由于0-10的相加的结果为11...不为自对齐4的倍数...补齐后为12
- //所以结果:sizeof(B) = 12
2.再来使用Pragma手工更改了字节对齐值的情况,先看看Struct C的定义:
- #pragma pack(2)
- struct C
- {
- //假设从0开始
- char a;//0
- int b;//2-5
- short c;//6-7
- };
- sizeof(C)的答案为8
Struct C的分析摘自网友总结:
step 1: 确定结构体C对齐值:选择成员中最大的对齐值,即int a,对齐值为4
step 2: 确定手工指定对齐值,使用手工指定的值:2
step 3: char a 的有效地址值=min(1,2),(因为0x0000%2=0),这样a的地址就是0x0000
step 4: int b 的有效对齐值=min(4,2),地址依次从0x0002~0x0005 (因为Ox0002%2=0)开始,分配4个字节,目前地址段分配情况就是:0x0000~0x0005
step 5: short c 的有效对齐值=min(2,2),由于要求考虑到对齐的情况,从0x0006(因为0x0006%2=0)开始,分配2个字节的地址0x0006~0x0007
目前为止,地址段的分配情况就是:0x0000~0x0007共8个字节,同时也保证了Struct C的对齐情况(2字节对齐,pragma(2)),sizeof(C)=8
结论:
最后的最后补多一个混合的例子:
- struct tagS1
- {
- //假设地址从0开始,这里最长的类型为_unT1,长度为8...
- //变量的首地址为地址模sizeof(变量类型)结果为0的地址开始
- char a;//0 (0模1==0,所以从0开始)
- int n;//4-7 (2和3模4不等于0,从4开始)
- _unT1 t1;//8-15(8模8等于0,从8开始)
- long l;//16-19(16模4等于0,从16开始)
- char sz[];//20-41(20模1等于0,从20开始)
- };
- //由于0-41的长度为42,42不为8的倍数,所以补长为8的倍数,结果为48
C++结构体字节对齐的更多相关文章
- [置顶]
什么是C语言结构体字节对齐,为什么要对齐?
一.概念 对齐跟数据在内存中的位置有关.如果一个变量的内存地址正好位于它长度的整数倍,他就被称做自然对齐.比如在32位cpu下,假设一个整型变量的地址为0x00000004,那它就是自然对齐的. ...
- C/C++结构体字节对齐详解
结构体的sizeof先看一个结构体:struct S1{ char c; int i;}; sizeof(S1)在VC6中按默认设置得到的结果为8.我们先看看sizeof的定义——size ...
- C语言 结构体字节对齐问题
摘选自这位大神的博客 方法一: 结构体在内存中分配一块连续的内存,但结构体内的变量并不一定是连续存放的,这涉及到内存对齐. 原则1 数据成员对齐规则:结构(struct或联合union)的数据成员, ...
- C/C++ 结构体字节对齐
在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题.从理论上讲,对于任何 变量的访问都可以从任何地址开始访问,但是事实上不是如此 ...
- 【c++】【转】结构体字节对齐
http://www.cnblogs.com/heyonggang/archive/2012/12/11/2812304.html
- C语言结构体的对齐原则
Q:关于结构体的对齐,到底遵循什么原则?A:首先先不讨论结构体按多少字节对齐,先看看只以1字节对齐的情况: #include <stdio.h> #include <string.h ...
- C语言 结构体(联合体)对齐规则
/* 结构体(联合体)对齐规则 */ #include <stdio.h> #include <stdlib.h> #include <string.h> /* * ...
- c中结构体边界对齐
原则1.普通数据成员对齐规则:第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储). 原则2 ...
- 再谈:自定义结构体的对齐问题之__attribute__ ((packed))方法【转】
转自:https://blog.csdn.net/ipromiseu/article/details/5955295 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.c ...
随机推荐
- QrenCode : 命令行下生成二维码图片
对于二维码大家应该并不陌生,英文名为 2-dimensional bar code 或 QR Code,是一种用图形记载信息的技术,最常见的是应用在手机应用上.用户通过手机摄像头扫描二维码或输入二维码 ...
- ASP.NET MVC中ViewBag和ViewData的区别
在MVC3.0以上我们会用到ViewBag或者ViewData进行页面传值,对比一下二者的差距: ViewData ViewBag 基于key/value的字典集合 dynamic类型对象 从ASP. ...
- 【转】C#中的Stream
C# 温故而知新:Stream篇(—) C# 温故而知新:Stream篇(二) C# 温故而知新:Stream篇(三) C# 温故而知新:Stream篇 (四) C# 温故而知新:Stream篇(五) ...
- hihocoder 1305 - 区间求差 - [hiho一下152周][区间问题]
题目链接:https://hihocoder.com/problemset/problem/1305 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定两个区间集合 A ...
- django比较相等或者不相等的模板语法ifequal / ifnotequal
转自:http://blog.csdn.net/goupper1991/article/details/50768346 ifequal / ifnotequal 在模板语言里比较两个值并且 ...
- ECharts修改坐标轴,坐标轴字体,坐标轴网格样式以及控制坐标轴是否显示
转自:http://blog.csdn.net/kirinlau/article/details/72876689 首先要将一个图表显示在前端页面上: var myChart = echarts.in ...
- 新购买的vps应该做的几件事情
1. 修改root密码 passwd root 2.新建用户 useradd vinentguo 3.配置免密码登陆 .使用新建用户登陆vps. mkdir ~/.ssh/ch ...
- arcgis api for JavaScript _跨域请求
arcgis api for JavaScript 中出现跨域请求是常见问题, 通常出现类似如下错误消息类似: XMLHttpRequest cannot load http://10.32.2.7 ...
- Linux下Miniconda量化环境安装
前言 linux目录相关知识 /usr:系统级的目录,可以理解为C:/Windows/,/usr/lib理解为C:/Windows/System32./usr/local:用户级的程序目录,可以理解为 ...
- HTML文件默认内容
<!DOCTYPE html> <!-- 声明使用html5标准 --> <html lang="en"> <!-- html标签开始(只 ...