gpt4 book ai didi

c - 为什么 -Wcast-align 不警告在 x86 上从 char* 到 int* 的转换?

转载 作者:太空狗 更新时间:2023-10-29 16:43:58 26 4
gpt4 key购买 nike

我知道 gcc 有一个选项 -Wcast-align,它会在每次转换指针时发出警告,从而增加目标的对齐要求。

这是我的程序:

char data[10];
int ptr = *((int *)data);

在我的机器上,数据的对齐要求是 1,而 ptr 是 8。

为什么我没有收到警告?

可能是因为我正在为 x86 编译它?

最佳答案

2020-05-10 更新:从 GCC 8 开始,编译器支持选项 -Wcast-align=strict,即使在正常情况下的目标上也会发出警告允许未对齐的内存访问。启用它可能是个好主意:the compiler is free to optimise code with the assumption that the pointers are aligned, even on targets that would otherwise not care .


当为这些系统使用标准 ABI 时,为 Linux i386 或 x86-64 编译时永远不会发出警告。让我来解释一下为什么会这样。

首先,让我们看看gcc's documentation是什么关于 -Wcast-align 不得不说:

Warn whenever a pointer is cast such that the required alignment ofthe target is increased. For example, warn if a char * is cast to anint * on machines where integers can only be accessed at two- orfour-byte boundaries.

Intel 架构在使用通用指令时不需要整数对齐。引自 Intel's Basic Architecture manual , 第 4.1.1 章字、双字、四字和双四字的对齐:

Words, doublewords, and quadwords do not need to be aligned in memoryon natural boundaries. The natural boundaries for words, double words,and quadwords are even-numbered addresses, addresses evenly divisibleby four, and addresses evenly divisible by eight, respectively.However, to improve the performance of programs, data structures(especially stacks) should be aligned on natural boundaries wheneverpossible.

因此,虽然强烈推荐,但对齐并不是绝对必要的。但是,该规则有一个异常(exception),您可能已经想到了。 EFLAGS 寄存器的第 18 位称为“对齐检查”位,CR0 寄存器的第 18 位称为“对齐掩码”标志。当它们都设置为 1 时,任何对未在其“自然边界”对齐的数据的内存访问(因此,字为 2 个字节,双字为 4 个字节,依此类推)导致 #AC对齐检查异常。如果您想了解更多信息,请查看 Intel System Programming Guide .

但是,System V ABI for i386 都不是,也不是 System V ABI for x86-64指定设置了 EFLAGS 中的对齐标志。事实上,i386 ABI 在第 29 页第 3-3 章 机器接口(interface) 中记录了以下内容:

The Intel386 architecture does not require all data access to beproperly aligned. (...) Consequently, arbitrary data accesses, such aspointers dereference or reference arguments, might or might not beproperly aligned. Accessing misaligned data will be slower thanaccessing properly aligned data, but otherwise there is no difference.

虽然它也建议:

Compilers should allocate independent data objects with the properalignment.

GCC 总是知道它为其编译代码的平台的 ABI,并且 - 在 x86/64 的情况下 - 知道允许未对齐数据访问的事实。这就是为什么像这样的代码将在没有对齐警告的情况下编译(让我们忘记以下示例中的严格别名规则):

int main(void)
{
char foo[] = "foobar";
int bar = *(int*)(foo + 1);
return 0;
}

如果您尝试使用 ARM 的 gcc 工具链编译此代码,您将收到警告:

daniel@Jurij:/tmp$ arm-linux-gnueabi-gcc -Wcast-align align.c 
align.c: In function 'main':
align.c:4:13: warning: cast increases required alignment of target type [-Wcast-align]
int bar = *(int*)(foo + 1);

这是因为在 ARM 中通常最好避免未对齐访问。我不是 ARM 专家,所以我真的不能说更多。

另外,请注意,我写的大部分内容不适用于 SSE/AVX。

关于c - 为什么 -Wcast-align 不警告在 x86 上从 char* 到 int* 的转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25762173/

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