现代计算机中的内存空间按字节划分. 从理论上讲,访问任何类型的变量似乎都可以从任何地址开始,但是实际情况是,访问特定变量时,通常是在特定的内存地址访问,这要求将各种类型的数据安排在其中. 按照某些规则排列空间,而不是一个接一个地排列.

为什么要地址对齐?

对齐的作用和原因: 每个硬件平台处理存储空间的方式都非常不同. 某些平台只能从某些地址访问某些类型的数据. 其他平台可能没有这些限制,但最常见的是,如果数据存储未根据平台的要求进行对齐,则会导致访问效率下降. 例如,某些平台每次都从偶数地址开始. 如果将int类型(假定为32位)存储在偶数地址的开头,则可以在一个时钟周期内读取它. 并且,如果将其存储在奇数地址的开头,则可能需要2个时钟周期,并且两次读取结果的高字节和低字节会拼凑在一起以获得int类型数据. 显然,读取效率下降很多. 这也是时空的游戏.

对齐的实现

通常,当我们编写程序时,我们不需要考虑对齐问题. 编译器将为我们选择适合目标平台的对齐策略. 当然,我们也可以通知编译器传递预编译的指令,以更改指定数据的对齐方式.

但是,这是因为我们通常不需要关心这个问题,并且因为编译器已经对齐了数据. 但是,如果我们不了解它,我们常常会对某些问题感到困惑. 最常见的是该结构的sizeof()结果,这是意外的. 为此,我们需要了解对齐算法.

对齐算法

由于平台和编译器之间的差异,我将以gcc版本3.2.2编译器(32位x86平台)为例,讨论编译器如何对齐结构的各个成员.

假定结构定义如下:

该结构包含一个长度为4个字节的int变量,一个长度为1个字节的char变量和一个长度为2个字节的short变量. 因此,结构A的长度应为4 + 1 + 2 = 7,但是由于编译器要在空间上对齐成员,因此sizeof(A)的值为8.

现在我们调整结构成员的顺序:

调整后的结构A的长度仍应为7,但sizeof(A)的值为12.

在这里,我们使用以下预编译指令来告诉编译器使用我们指定的对齐值2而不是默认值.

#pragma pack(值)

#pragma pack(2)/ *将对齐值指定为2 * / struct A {char b;诠释短c;}; #pragma pack()/ *取消指定的对齐值,并使用默认值. * /

sizeof(A)的值为8.

将对齐值修改为1:

#pragma pack(1)/ *将对齐值指定为1 * / struct A {char b;诠释短c;}; #pragma pack()/ *取消指定的对齐值c 计算结构体大小,并使用默认值. * /

sizeof(A)的值为7.

在这里,我们将详细解释为什么会这样?

首先了解四个概念:

基本数据类型本身的对齐值: 它是基本数据的长度,例如sizeof(char),sizeof(int),sizeof(short).

指定的对齐值: 使用#pragma pack(值)指令指定的值.

导出数据类型的自对准值: 在其成员中具有最大自对准值的数据类型.

已导出数据类型的有效对齐值: 其自身的对齐值和指定的对齐值较小.

使用这些值,我们可以轻松地讨论特定数据结构的成员及其自身的对齐方式. 有效对齐值N是最终用于确定数据如何存储在地址中的值,并且是最重要的值. 有效地对齐N意味着“对齐N”,即数据的“存储起始地址%N = 0”. 数据结构中的数据变量按定义的顺序排列. 第一个数据变量的起始地址是数据结构的起始地址. 结构的成员变量应对齐并释放,并且结构本身应根据其有效对齐值进行四舍五入(即,结构成员变量的总长度必须是结构有效对齐值的整数倍)结构,结合下面的示例了解). 理解上面示例的值并不难.

分析示例B:

假定B开始从地址空间0×0000放电. 在此示例中,未定义指定的对齐值. 在作者的环境中,该值默认为4. 第一个成员变量b的自对准值是1,小于指定的或默认指定的对准值4,因此其有效对准值为1c 计算结构体大小,因此其存储地址0×0000符合0×0000%1 =0. 第二个成员变量a具有其自己的对齐值4,因此有效对齐值也为4,因此它只能存储在四个连续的字节空间中,且a起始地址0×0004到0×0007,并检查0×0004%4 = 0,并在第一个变量旁边. 第三个变量c,自对准值为2,因此有效对准值也为2,可以将其存储在两个字节空间0×0008到0×0009中,与0×0008%2 = 0一致. 因此,B的内容存储范围为0×0000到0×0009. 从数据结构B的自对准值来看,其变量(此处为b)的最大对准值为4,因此该结构的有效对准值为也4.根据结构的圆度要求,0×0009到0×0000 = 10字节,(10 + 2)%4 =0. 所以结构B也占用了0x0000A到0x000B. 所以B有12个字节从0×0000到0x000B,sizeof(结构B)= 12;

类似地,分析上面的示例C:

#pragma pack(2)/ *指定2字节对齐* / struct C {char b;诠释短c;}; #pragma pack()/ *取消指定的对齐方式并恢复默认对齐方式* /

第一个变量b的自对准值是1,指定的对准值是2. 因此,其有效对准值是1. 假定C从0×0000开始,则b存储在0×0000中. ,与0×0000%1 = 0一致;第二个变量,自对准值为4,指定的对准值为2,因此有效对准值为2,因此将顺序存储在以下四个值中: 0×0002、0×0003、0×0004、0×0005在连续字节中,它是0×0002%2 =0. 第三个变量c的自对准值是2,因此有效对准值是2,并且顺序存储在0×0006、0×0007中,与0×0006%2 = 0一致. 因此,从0×0000到0×00007总共有八个字节是C变量. 并且C的自对准值为4,因此C的有效对准值为2. 8%2 = 0,C仅占用从0×0000到0×0007的八个字节. 因此sizeof(结构C)= 8.

通过以上解释,我相信您应该对C语言中字节对齐的概念有清楚的了解. 在网络程序中,掌握这一概念非常重要. 要在不同平台之间(例如Windows和Linux之间)传递二进制流(例如结构),则必须将两个平台定义为相同. 摄像机的对齐方式是莫名其妙的错误,但是很难解决^ _ ^

发件人:

本文来自电脑杂谈,转载请注明本文网址:

http://www.pc-fly.com/a/jisuanjixue/article-214503-1.html

c语言地址和地址怎么比较大小,C语言地址对齐(转)-计算网络编程的结构大小...相关推荐

  1. 网络编程懒人入门(九):通俗讲解,有了IP地址,为何还要用MAC地址?

    1.前言 标题虽然是为了解释有了 IP 地址,为什么还要用 MAC 地址,但是本文的重点在于理解为什么要有 IP 这样的东西.本文对读者的定位是知道 MAC 地址是什么,IP 地址是什么. (本文同步 ...

  2. Windows下C语言网络编程快速入门

    C语言的学习,一般的方式是,先学C,然后是C++,最好还要有汇编语言和微机原理基础,然后才是Visual C++.这样的方式,对学习者来说,要花费很多时间和耐力.而在学校教学中,也没有时间深入学习Wi ...

  3. C语言的数组名和对数组名取地址

    *************************************************** 更多精彩,欢迎进入:http://shop115376623.taobao.com ****** ...

  4. 用Go语言建立一个简单的区块链part5:地址

    地址 引言 在上一篇文章中,我们已经初步实现了交易.相信你应该了解了交易中的一些天然属性,这些属性没有丝毫"个人"色彩的存在:在比特币中,没有用户账户,不需要也不会在任何地方存储个 ...

  5. C语言中二维数组名与数组地址、首行地址、首行首元素地址关系与区别详解(初学者必须掌握)

    C语言作为很多大学理工科都会学习的语言,作为一种编程入门语言. 但是相对于其他高级编程语言来说相对是比较难,尤其是指针,不知道有多少莘莘学子都是因为它,从C语言入门到放弃. 想当年,笔者在大一学习C语 ...

  6. C语言数组和指针的理解_在取地址运算上的操作_指针加减操作_a 和a 的区别

    1.一个实例+理论分析 在了解数组和指针的访问方式前提下,下面再看这个例子: main() { int a[5]={1,2,3,4,5}; int *ptr=(int *)(&a+1); pr ...

  7. c语言地址有什么作用是什么,C语言中取地址运算符是什么?

    在C语言中取地址运算符是"&"."&"作为一元运算符,结果是右操作对象的地址:地址本身是一个抽象的概念,用于表示对象在存储器中的逻辑位置. 在C ...

  8. 操作系统-文件管理习题详细解析:设文件索引结点中又7个地址项,其中4个地址项是直接地址索引,2个地址项是一级间接地址索引,1个地址项是二级间接索引,每个地址项大小为4B,若磁盘索引块和磁盘数据块大小均

    题目:设文件索引结点中又7个地址项,其中4个地址项是直接地址索引,2个地址项是一级间接地址索引,1个地址项是二级间接索引,每个地址项大小为4B,若磁盘索引块和磁盘数据块大小均为256B,则可表示的单个 ...

  9. C语言加取址符的作用,C语言中指针和取地址符的关系

    一 概念定义: 严格说起来,应该这么讲:指针存的是地址,而&运算符是取变量的地址. 指针原理: 其实计算机中的内存就像一个个抽屉(一兆内存就相当于1百万个抽屉),每个抽屉都有一个编号,用于存放 ...

最新文章

  1. MySQL 数据库sql命令查看表属性,mysql查看指定表的各字段最大值、是否为空等属性实例演示
  2. python正则group()的用法—正则提取括号内以及其他符号内内容
  3. C++ vector中的resize,reserve,size和capacity函数讲解
  4. JavaTPoint 数据库教程【翻译完成】
  5. vm虚拟机安装lede旁路由_vmware虚拟机下安装lede软路由
  6. python广度优先算法最短路径_最短路径问题的Dijkstra算法 -python
  7. load data file使用详解
  8. 使用SQLyog创建表
  9. idea导出文件支持目录结构
  10. 各个版本eclipse官方下载地址
  11. 联想笔记本热键与IDEA快捷键冲突问题
  12. wpsa4排版_如何用WPS快速排版
  13. C++引用计数原理和实现
  14. 简易计算器(C语言实现)
  15. 二叉排序树和平衡二叉树
  16. JPG图片怎么转换成Word
  17. android--GooglePay 谷歌支付内购接入(2)
  18. notes-ThinkCMF视频教程 第一期(网易云课堂)
  19. 进入游戏后如何回到计算机界面,网易云我的世界电脑版怎样回到游戏主界面 | 手游网游页游攻略大全...
  20. 十款PHP开发框架横向比较

热门文章

  1. 苹果手机软件升级密码_金太阳手机软件升级啦!全面支持科创板行情和交易!...
  2. Linux 快速基础篇__Linux操作系统
  3. C++ 函数模板 使用模板数组排序
  4. 【VC++ MFC】vc 画笔和画刷|OnDraw()和OnPaint()
  5. 微信平台——微信公众号简单介绍
  6. MacOS 日历和群晖日历同步问题解决
  7. mongodb导出csv格式文件,使用excel打开乱码解决
  8. MES系统下设备管理系统操作简单,功能强大,欢迎了解使用
  9. 数据分析--异常值处理
  10. this和super关键字详解