关于字节对齐的几点疑问

weiwuyuan 2013-06-08 02:53:12
首先百度百科这样解释:
"现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。"

这个解释,感觉不太明朗,就是解释了一个问题的同时,又引出了新的问题,我指的是:"但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问", 什么叫特定的类型变量? 举个例子?

另一个问题是出自别人的话:
"即使看起来本来就自然对齐的也要使其对齐,以免不同的编译器生成的代码不一样."
意思是,"int a"这样的变量是4字节自然对齐的, 如果某种指令限定一个变量必须按4字节对齐,那么也得加上类似"__declspec(align(4))" 这样的声明?
...全文
280 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
失散糖 2013-06-10
  • 打赏
  • 举报
回复
赵老师也说过,不要迷信老师
赵4老师 2013-06-10
  • 打赏
  • 举报
回复
引用 22 楼 sugar13 的回复:
赵老师也说过,不要迷信老师
不要迷信书、考题、老师、回帖; 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实! 使用电脑计时有时误差会很大,因为待测程序段的运行会影响电脑时钟。 将待测程序段循环足够多次,手动掐秒表计时可能更准确。
失散糖 2013-06-10
  • 打赏
  • 举报
回复
引用 23 楼 zhao4zhong1 的回复:
[quote=引用 22 楼 sugar13 的回复:] 赵老师也说过,不要迷信老师
不要迷信书、考题、老师、回帖; 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实! 使用电脑计时有时误差会很大,因为待测程序段的运行会影响电脑时钟。 将待测程序段循环足够多次,手动掐秒表计时可能更准确。 [/quote] 那个..虽然我也不是太清楚,不过,电脑时钟不是和程序不相干的吗?就算电脑关机了,那个时钟仍然在跑啊,除非恶意篡改时钟的时间,否则程序的运行怎么会影响到电脑时钟的呢? 本人小白,请赵老师指点
lm_whales 2013-06-09
  • 打赏
  • 举报
回复
现代计算机中内存空间都是按照byte划分的???? 这个只有微机系统是这样的吧。 很多CPU是WORD,DWORD 编址的,每个内存地址,对应16BITS,32BITS等等; 按照BYTE对齐,对于这种CPU,就等于找死了!!!
十八道胡同 2013-06-09
  • 打赏
  • 举报
回复
我是来看赵老师的。。
「已注销」 2013-06-09
  • 打赏
  • 举报
回复
引用 19 楼 lm_whales 的回复:
有些处理器的异常是出错,不是继续处理, X86因为一直以来就是按照BYTE,计算地址的所以,没有问题。 对齐异常是读写异常,就像保护出错一样,不会修正后再运行的。是实实在在的错误!! X86不是处理器的全部!!!!
继续处理又不是让处理器自己去处理。。处理器是产生一个异常中断,自己可以接收处理的,有些系统就会修正地址,分多次读取,然后拼凑返回跟需要这份数据的程序。
lm_whales 2013-06-09
  • 打赏
  • 举报
回复
有些处理器的异常是出错,不是继续处理, X86因为一直以来就是按照BYTE,计算地址的所以,没有问题。 对齐异常是读写异常,就像保护出错一样,不会修正后再运行的。是实实在在的错误!! X86不是处理器的全部!!!!
「已注销」 2013-06-09
  • 打赏
  • 举报
回复
引用 13 楼 lm_whales 的回复:
alpha处理器VC支持,不对齐会有异常;BYTE绝对不行; arm,dsp 的地址是16BITS或者32BITS
跟地址毛线关系,你说的byte绝对不行是什么情况呢,难道char a[10]; a[0],a[1]...访问就报错?这样的话,你这处理器可以淘汰了。只有在PDWORD pa = &a[1],然后去操作pa的时候处理器会抛异常。x86处理器也可以设置在0x401001读取word、DWORD抛异常,但是系统还是会处理这个异常,把数据修正继续运行,不过一般系统都不蛋疼的去打开这个异常位。 地址16位、32位只是说默认对齐方式不一样,还有sizeof(int)值不一样。
worldy 2013-06-09
  • 打赏
  • 举报
回复
引用 12 楼 whizer 的回复:
这个问题查查地址总线和数据总线,了解一下具体的内存访问原理应该就可以解释你的问题了。 举个简单例子:假设一款CPU,地址和数据总线为32位。也就是说一次CPU读操作可以获得4字节(32bit)的数据。那么现在有两个数据,即char ch_val; int int_val;如果按照一个字节一个地向内存中存取数据,且存取的起始位置0x10000。那么存储后数据的存储方式为: (其中int_val有4个字节数据组成,分别是 int_val0 ... int_val3). -------------------------------------------- 0x1000 | cha_val | int_val3 | int_val2 | int_val1 | -------------------------------------------- 0x1004 | int_val0| | | | -------------------------------------------- 现在如果要CPU要访问int_val,那么就需要二次访问内存,一次先访问0x1000,一次访问0x1004,然后把二次访问的结果提取并合并为int_val。然而如果int_val如果地址对齐的话一次就够了。而内存的访问速度比cpu速度要慢至少一个数量级。当程序很大,数据较多的时候,你可以想象一下你的程序速度........ 顺便说一句,现在几乎所有的cpu都支持非对齐地址访问。
应该说x86系cpu,从来都能支持非对齐地址访问,只是对非对齐地址访问,效率低而已
worldy 2013-06-09
  • 打赏
  • 举报
回复
引用 楼主 weiwuyuan 的回复:
首先百度百科这样解释: "现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。" 这个解释,感觉不太明朗,就是解释了一个问题的同时,又引出了新的问题,我指的是:"但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问", 什么叫特定的类型变量? 举个例子? 另一个问题是出自别人的话: "即使看起来本来就自然对齐的也要使其对齐,以免不同的编译器生成的代码不一样." 意思是,"int a"这样的变量是4字节自然对齐的, 如果某种指令限定一个变量必须按4字节对齐,那么也得加上类似"__declspec(align(4))" 这样的声明?
特定类型变量,比如int类型,4个字节,其首地址肯定是4n 比如double 8个字节,其首地址也肯定是4n 编译器这么处理是为了效率 对于32位系统,其数据宽度为32/8=4字节,也就是说,cpu访问内存一个周期可以直接读取4字节数据,总线的32位就和4字节对应, 如果出现不对齐的内存,同样要读取32位,则必须话费一些周期将数据调整和总线对齐,这样访问效率就低了,因此,编译器总是尽可能的在效率和内存间进行平衡
赵4老师 2013-06-09
  • 打赏
  • 举报
回复
MMX指令好象明确要求16字节对齐。
赵4老师 2013-06-09
  • 打赏
  • 举报
回复
谁帮忙断个帖呗? http://bbs.csdn.net/topics/390485431 先谢了!
lm_whales 2013-06-09
  • 打赏
  • 举报
回复
alpha处理器VC支持,不对齐会有异常;BYTE绝对不行; arm,dsp 的地址是16BITS或者32BITS
whizer 2013-06-09
  • 打赏
  • 举报
回复
这个问题查查地址总线和数据总线,了解一下具体的内存访问原理应该就可以解释你的问题了。 举个简单例子:假设一款CPU,地址和数据总线为32位。也就是说一次CPU读操作可以获得4字节(32bit)的数据。那么现在有两个数据,即char ch_val; int int_val;如果按照一个字节一个地向内存中存取数据,且存取的起始位置0x10000。那么存储后数据的存储方式为: (其中int_val有4个字节数据组成,分别是 int_val0 ... int_val3). -------------------------------------------- 0x1000 | cha_val | int_val3 | int_val2 | int_val1 | -------------------------------------------- 0x1004 | int_val0| | | | -------------------------------------------- 现在如果要CPU要访问int_val,那么就需要二次访问内存,一次先访问0x1000,一次访问0x1004,然后把二次访问的结果提取并合并为int_val。然而如果int_val如果地址对齐的话一次就够了。而内存的访问速度比cpu速度要慢至少一个数量级。当程序很大,数据较多的时候,你可以想象一下你的程序速度........ 顺便说一句,现在几乎所有的cpu都支持非对齐地址访问。
疯狂的红豆 2013-06-09
  • 打赏
  • 举报
回复
关于内存对齐MS的编译器也有选择项的,_declspec关键字是MS的对于变量存储的扩充属性 链接不错,将_declspec修饰符的http://wenku.baidu.com/view/61232f0b79563c1ec5da719f.html
「已注销」 2013-06-09
  • 打赏
  • 举报
回复
引用 6 楼 lm_whales 的回复:
现代计算机中内存空间都是按照byte划分的???? 这个只有微机系统是这样的吧。 很多CPU是WORD,DWORD 编址的,每个内存地址,对应16BITS,32BITS等等; 按照BYTE对齐,对于这种CPU,就等于找死了!!!
那意思其实是说读取内存最小单位是byte,目前好像没见过不是byte的处理器。。不过以前的处理器最小读写单位从1bit到64bits都出现过
「已注销」 2013-06-09
  • 打赏
  • 举报
回复
数据要求对齐的原因--效率跟某些处理器会发生异常。看这里 http://blog.csdn.net/lgouc/article/details/8235471 一般来说数据会对齐到边界上的,也就是: 存放该数据的地址 % sizeof(数据类型) = 0 另外对齐也看编译器默认的对齐方式,你目前都用不到这东西,到时候解析数据的时候再学没关系,你自己写的结构无所谓大小对齐否,让编译器变成默认形式即可
lm_whales 2013-06-09
  • 打赏
  • 举报
回复
引用 7 楼 zhao4zhong1 的回复:
[quote=引用 6 楼 lm_whales 的回复:] 现代计算机中内存空间都是按照byte划分的???? 这个只有微机系统是这样的吧。 很多CPU是WORD,DWORD 编址的,每个内存地址,对应16BITS,32BITS等等; 按照BYTE对齐,对于这种CPU,就等于找死了!!!
请搜“地址总线 RAM读写电路” 忍不住显摆一下:偶本科专业是计算机应用(偏硬件:与非门、单片机、集成电路啥的),研究生专业是计算机图形图象处理。 [/quote] 佩服,佩服! 既然如此,以后就要多多请教一番了,还望不吝赐教! 另外这里,丝毫没有针对赵老师的意思!!!
赵4老师 2013-06-09
  • 打赏
  • 举报
回复
引用 6 楼 lm_whales 的回复:
现代计算机中内存空间都是按照byte划分的???? 这个只有微机系统是这样的吧。 很多CPU是WORD,DWORD 编址的,每个内存地址,对应16BITS,32BITS等等; 按照BYTE对齐,对于这种CPU,就等于找死了!!!
请搜“地址总线 RAM读写电路” 忍不住显摆一下:偶本科专业是计算机应用(偏硬件:与非门、单片机、集成电路啥的),研究生专业是计算机图形图象处理。
慧钦 2013-06-08
  • 打赏
  • 举报
回复
引用 4 楼 zhao4zhong1 的回复:
计算机组成原理(数字逻辑电路、地址总线、RAM读写电路、……)→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构……
虽然眼过千行不如手敲一行,但还是希望看到老师在理论的推荐,能不能在每个相应的部分介绍一两本书来看。
加载更多回复(4)

64,318

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧