gpt4 book ai didi

C 避免对齐问题

转载 作者:行者123 更新时间:2023-12-02 20:22:48 24 4
gpt4 key购买 nike

能否请一些人解释一下,下面的例子到底出了什么问题,尤其是“可能导致从不是四的倍数的地址加载 32 位无符号长整型”的部分:

"The compiler generally prevents alignment issues by naturally aligning all data types. In fact, alignment issues are normally not major concerns of the kernel developersthe gcc folks have to worry about them. Issues arise, however, when the programmer plays too closely with pointers and accesses data outside the environment anticipated by the compiler.

Accessing an aligned address with a recast pointer of a larger-aligned address causes an alignment issue (whatever that might mean for a particular architecture). That is, this is bad news:

char dog[10];
char *p = &dog[1];
unsigned long l = *(unsigned long *)p;

This example treats the pointer to a char as a pointer to an unsigned long, which might result in the 32-bit unsigned long being loaded from an address that is not a multiple of four.

If you are thinking, "When in the world would I do this?" you are probably right. Nevertheless, it has come up, and it will again, so be careful. The real-world examples might not be so obvious."

虽然我不是很理解这个问题,但是否可以使用下面的代码解决它,如果可以,为什么?

char * dog = (char *)malloc(10 * sizeof(char));
char *p = dog +1;
unsigned long l = *(unsigned long*)p;

最佳答案

你引用的这段话完全正确。

大多数情况下,您不必担心对齐问题,因为编译器会为您处理好它,并且效果很好,除非您做的事情非常松鼠以至于成功挫败了编译器保护的尝试你。

当您调用malloc 时,没有问题,因为malloc 很特殊(在几个方面)。除其他外,它“保证返回一个指针,指向适合任何类型对象对齐的存储。”

但是,是的,如果你为此努力,你可能会给自己带来麻烦。回到最初的例子,假设我们有

char dog[] = "My dog Spot";
char *p = &dog[0];
unsigned long l = *(unsigned long *)p;

假设数组在内存中的布局是这样的:

      +---+---+---+---+
100: | | | M | y |
+---+---+---+---+
104: | | d | o | g |
+---+---+---+---+
108: | | S | p | o |
+---+---+---+---+
112: | t |\0 | | |
+---+---+---+---+

也就是说,假设数组 dog 结束于内存地址 102,它不是 4 的倍数。所以指针 p 也指向地址 102,我们尝试访问地址 102 处的 long int。(您会注意到我已将其更改为 &dog[0],而不是 &dog[1] 在原始示例中,试图使事情更清楚一些。)

所以我们可能期望变量 l 最终包含 1299783780 或 1679849805(即 0x4d792064 或 0x6420794d),因为它们是前四个字节“My d”的表示big-endian 或 little-endian 表示。

但由于它是一个未对齐的访问,我们可能两个都得不到;该程序可能会因类似“总线错误”的错误而崩溃。

如果我们有义务并决心要做这种事情,我们可以设法自己进行对齐,像这样:

char dog[] = "My dog Spot";
char *p = dog;
int al = (intptr_t)p % sizeof(unsigned long);
al = sizeof(unsigned long) - al;
if(al == sizeof(unsigned long)) al = 0;
p += al;
unsigned long l = *(unsigned long *)p;

当然,移动指针 p 直到它指向 4 的适当倍数,它不再指向“My d”;现在它指向“狗”。

我做过一两次这种事情,但我真的不能推荐它。

关于C 避免对齐问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50899212/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com