请教 C 语言中, gcc 编译器 对未对其的访问是怎么处理的呢?

2018-02-13 19:58:38 +08:00
 p64381

平台为 x86 或者 路由器常见的 MIPS x86 gcc 7.3 MIPS gcc 7.5

比如这个代码

char buf[10];
uint32_t *p = (uint32_t *) (buf+1); // p 指向没有 4 字节对其的地址。

// 下面的各种操作也都是正常的 (至少运行起来是正常的)
*p = 0x12345678;
*p = *p + 1;

这样没有对其的情况下会有什么影响呢? “对齐”操作是编译器工作还是 CPU 的工作呢? 会有多大效率差别呢?

2200 次点击
所在节点    问与答
8 条回复
WordTian
2018-02-13 21:32:24 +08:00
内存数据对齐,和硬盘 4K 对齐起的作用类似啊。

内存也是由很多个块组成的,没对齐的话,很多数据就会同时存在两个块中,就要从两个块中进行读取。

效率的话,取决于你的数据类型,块大小,和 CPU 从内存中取数据的机制吧应该
WordTian
2018-02-13 21:37:02 +08:00
有些嵌入式设备的 CPU 就没有从两个块中取数据再提取合并的机制,碰上这种情况应该就抓瞎了
xwyam
2018-02-13 23:04:36 +08:00
我在 Cavium 的 MIPS 下遇到过问题的。还是建议声明一个 int 变量,用 memcpy 在变量和缓冲区之间复制数据,这样一般没有坑。
wzxlovesy
2018-02-14 00:04:41 +08:00
一般机器都是 32 位机器,所以一次操作 4 字节是有效的,注意大小头,注意越界就行
changnet
2018-02-14 00:12:54 +08:00
这个是分为两种情况的
1. 编译器在编译的时候能识别,会自动帮你对齐,损失一些效率但不是很大
2.cpu 指令支持不对齐数据读取,比如 x86 cpu,也只是影响一些效率
3.cpu 不支持不对齐数据读取,程序应该是挂掉
congeec
2018-02-14 02:09:36 +08:00
编译器咋处理的我不清楚,得看汇编代码
不过我确定栈已经破坏了,这程序吃枣药丸
zwyc
2018-02-14 08:43:24 +08:00
楼主的示例中,代码就是要去访问一个非对齐的地址,编译器是不会去帮忙做对齐的。如果去做就是改变了原有的代码行为。编译器就是做了错误的优化。
ironx
2018-02-14 13:51:51 +08:00
@zwyc 正解。arm 不支持非对齐访问,会上报异常。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/430622

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX