前几天一个在自学C语言的小伙伴问了我个问题,C语言结构体储存所占空间为啥和自己预测的不一样。看一下下面这一段代码:

struct node{
int num;
char ch;
}a;
printf("%d",sizeof(a));

  在我们主动去申请内存的角度看来,申请一个上面的结构体,sizeof( int ) = 4; sizeof( char ) =1; sizeof( node ) 应该等于5才对,但是程序运行得出的却是8。

  小伙伴对于这个结果很是不解。这其实是C\C++ 储存规则中的内存对齐(字节对齐)原则。

一 什么是字节对齐
  现代计算机中,内存空间按照字节划分,理论上可以从任何起始地址访问任意类型的变量。但实际中在访问特定类型变量时经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序一个接一个地存放,这就是对齐。

二 对齐的原因和作用
  不同硬件平台对存储空间的处理上存在很大的不同。某些平台对特定类型的数据只能从特定地址开始存取,而不允许其在内存中任意存放。例如Motorola 68000 处理器不允许16位的字存放在奇地址,否则会触发异常,因此在这种架构下编程必须保证字节对齐。

  但最常见的情况是,如果不按照平台要求对数据存放进行对齐,会带来存取效率上的损失。比如32位的Intel处理器通过总线访问(包括读和写)内存数据。每个总线周期从偶地址开始访问32位内存数据,内存数据以字节为单位存放。如果一个32位的数据没有存放在4字节整除的内存地址处,那么处理器就需要2个总线周期对其进行访问,显然访问效率下降很多。

  因此,通过合理的内存对齐可以提高访问效率。为使CPU能够对数据进行快速访问,数据的起始地址应具有“对齐”特性。比如4字节数据的起始地址应位于4字节边界上,即起始地址能够被4整除。

  单纯的文字说明还是没那么好理解,下面我将通过几程序来让我们更清楚的了解到什么是内存对齐。ps: int的内存大小会随着操作系统的位数发生变化

#include "stdio.h"
struct node1 {
char a;char b;
};
struct node2 {
short a;char b;
};
struct node3 {
int a;char b;
};
struct node4 {
long a;char b;
};
struct node5 {
double a;char b;
};
int main() {
node1 char_char;
node2 short_char;
node3 int_char;
node4 long_char;
node5 double_char;               //程序输出:
printf("%d\n",sizeof(char_char));      // 2
printf("%d\n",sizeof(short_char));      // 4
printf("%d\n",sizeof(int_char));    // 8
printf("%d\n",sizeof(long_char));      // 8
printf("%d\n",sizeof(double_char));     // 16
return ;
}

  从上面这段代码及其输出结果,我们能够较为清晰的看到每个结构体的所占空间大小,均为其占内存较大的单位变量大小的倍数。

  然后考虑到如果我们需要在一个结构体内存很多个不同单位的变量时候是怎么存的呢?

#include "stdio.h"
struct node{
char ch; char ch1;
short st; char ch2;
int it; char ch3;
double db;char ch4;
}nd;
int main(){ //程序输出:
printf("%d",sizeof(nd)); //32
return ;
}

  这下又让人迷惑了,虽然确实是 较大内存的double类型的整数倍 3*8 但是具体怎么储存的呢,我们输出一下这个结构体每个子成员的地址。

    printf("&ch=0x%X   &ch1=0x%X   &st=0x%X   &ch2=0x%X \n",&nd.ch,&nd.ch1,&nd.st,&nd.ch2);
printf("&it=0x%X &ch3=0x%X &db=0x%X &ch4=0x%X \n",&nd.it,&nd.ch3,&nd.db,&nd.ch4);

这样有点抽象,不妨画个图:

可以很明显看到,图表中的所有地址就是整个结构体占用的所有空间。 内存申请空间以double对齐。交换一下结构体的声明顺序:

struct node{
char ch; char ch1;
int it; char ch3;
short st; char ch2;
char ch4; double db;
}nd;

  这下算比较清晰了,int类型以四个字节进行对齐,short类型以两个字节进行对齐,char类型在对齐规则下进行单字节填充。

  所以可以看到在定义结构体的时候进行适当的元素顺序调整可以有效的节省内存空间。

  包含字符串的结构体也是如此:

  

当然我们也可以通过 #pragma pack(n) 来改变这个内存对齐的方式:

#include "stdio.h"
#pragma pack(1)//设定为 1 字节对齐
double a;
struct node{
char ch; char ch1;
int it; char ch3;
short st; char ch2;
char ch4; double db;
}nd;
int main(){
printf("%d\n",sizeof(nd));
printf("&ch=0x%X &ch1=0x%X &st=0x%X &ch2=0x%X \n",&nd.ch,&nd.ch1,&nd.st,&nd.ch2);
printf("&it=0x%X &ch3=0x%X &db=0x%X &ch4=0x%X \n",&nd.it,&nd.ch3,&nd.db,&nd.ch4);
return ;
}

内存对齐调整前

内存对齐调整后

调整内存就会出现前面文本所说处理器访问效率变低的问题。

C\C++ 内存对齐现象的更多相关文章

  1. 为什么要内存对齐 Data alignment: Straighten up and fly right

    转载于http://blog.csdn.net/lgouc/article/details/8235471 为了速度和正确性,请对齐你的数据. 概述:对于所有直接操作内存的程序员来说,数据对齐都是很重 ...

  2. C/C++的内存对齐

    1.内存对齐之pragma pack语法 语法:#pragma pack( [show] | [push | pop] [, identifier], n )作用:指定结构,联合和类的包对齐方式(pa ...

  3. Sword 计算机内存对齐

    内存对齐理论 a.数据的对齐(alignment) 指数据的地址和由硬件条件决定的内存块大小之间的关系.一个变量的地址是它大小的倍数的时候,这就叫做自然对齐(naturally aligned). 例 ...

  4. C++继承体系中的内存对齐

    本篇随笔讨论一个比较冷门的知识,继承结构中内存对齐的问题,如今内存越来越大也越来越便宜,大部分人都已经不再关注内存对齐的问题了.但是作为一个有追求的技术人员,实现功能永远都是最基本的要求,把代码优化到 ...

  5. struct结构体大小的计算(内存对齐)

    本次实验环境 环境1:Win10, QT 5.12 一. 背景 当普通的类型无法满足我们的需求的时候,就需要用到结构体了.结构体可衍生出结构体数组,结构体还可以嵌套结构体,这下子数据类型就丰富多彩了, ...

  6. 重磅硬核 | 一文聊透对象在 JVM 中的内存布局,以及内存对齐和压缩指针的原理及应用

    欢迎关注公众号:bin的技术小屋 大家好,我是bin,又到了每周我们见面的时刻了,我的公众号在1月10号那天发布了第一篇文章<从内核角度看IO模型的演变>,在这篇文章中我们通过图解的方式以 ...

  7. C++内存对齐总结

    大家都知道,C++空类的内存大小为1字节,为了保证其对象拥有彼此独立的内存地址.非空类的大小与类中非静态成员变量和虚函数表的多少有关. 而值得注意的是,类中非静态成员变量的大小与编译器内存对齐的设置有 ...

  8. C/C++: C++位域和内存对齐问题

    1. 位域: 1. 在C中,位域可以写成这样(注:位域的数据类型一律用无符号的,纪律性). struct bitmap { unsigned a : ; unsigned b : ; unsigned ...

  9. C/C++ 知识点1:内存对齐

    预备知识:基本类型占用字节 在32位操作系统和64位操作系统上,基本数据类型分别占多少字节呢? 32位操作系统: char : 1    int :4    short : 2    unsigned ...

随机推荐

  1. 浏览器将URL变成一个屏幕上显示的网页的过程?

    前言 一个浏览器是怎么工作的? 正文 URL变网页过程: 1.浏览器通过http或https协议,向服务端请求页面 2.将请求过来的HEML代码通过解析,构建DOM树 3.计算DOM树上的CSS属性 ...

  2. Arch Linux 记录

    2017.1.8 开始花了两天装 Arch Linux,因为是第一次安装 Arch Linux,所以过程中遇到许多问题,特记录如下. 安装过程及遇到的问题: 下载镜像,刻盘. 重启进入 LiveCD ...

  3. element-ui多选框模糊搜索输入文字闪动问题

    .el-select__tags { .el-select__input { width: 50px !important; } } 添加这段代码即可 <el-select v-model=&q ...

  4. scrollview 嵌套imageview显示长图

    起初使用代码如下:但是图片显示不全,上半截被截 <ScrollView android:layout_width="match_parent" android:layout_ ...

  5. JMX - JMX定义

    JMX定义 JMX超详细解读 https://www.cnblogs.com/dongguacai/p/5900507.html 开源框架是如何通过JMX来做监控的(一) - JMX简介和Standa ...

  6. expect 批量自动部署ssh 免密登陆 之 三

    #!/bin/expect -- ########################################## zhichao.hu #Push the id.pas.pub public k ...

  7. pwnable.tw silver_bullet

    产生漏洞的原因 int __cdecl power_up(char *dest) { char s; // [esp+0h] [ebp-34h] size_t new_len; // [esp+30h ...

  8. linux查找删除某天前的文件(转载)

    语句写法:find 对应目录 -mtime +天数 -name "文件名" -exec rm -rf {} \; 例1: 将/usr/local/backups目录下所有10天前带 ...

  9. IIS+nginx反向代理 负载均衡

    本文没有过多的讲述,只讲述重点地方.由这两个转自的文章进行中和 1.nginx+iis实现负载均衡(这篇文章主要是有第2篇文章的工具) 2.nginx+iis使用(这篇文章讲得很详细,配置文件直接复制 ...

  10. selenium+python编写自动化脚本时,定位frame中对象操作

    在web应用中经常会出现frame嵌套的应用,假设页面上有A,B两个frame,其中B在A内,那么定位B中的内容则需要先到A,再到B.switchTo().frame方法可以把当前定位的主题切换到fr ...