- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我知道 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/
我有一个类型为 const char * 的变量 k,以及一个带有原型(prototype)的 glib 函数 void g_hash_table_replace(GHashTable *hash_t
我收到以下警告: cast between incompatible function types from ‘int (*)(pile *)’ {aka ‘int (*)(struct pile *
我正在阅读 an introduction to gcc其中说: ‘-Wcast-qual’ this option warns about pointers that are cast to rem
所以我有以下最小化的 C11 代码,它定义了一个包含 uint16_t 的结构(这意味着它应该对齐到 2 个字节的结构),我想将一个 char 缓冲区转换为指向该结构的指针。 随着警告全部出现,cla
如果我们有void foo(const char * const ** bar);我们用 char *** bar = malloc(...); 来调用它如foo((const char * cons
对于代码: static const char *a = NULL; abc((char **)&a); abc 方法定义为: abc(char** a) 我收到错误(警告被视为错误): erro
我知道 gcc 有一个选项 -Wcast-align,它会在每次转换指针时发出警告,从而增加目标的对齐要求。 这是我的程序: char data[10]; int ptr = *((int *)dat
编辑:问题解释得更深入 here (谢谢@Eric Postpischil)。这似乎是 GCC 中的一个错误。 首先,让我从一些上下文开始:我正在编写的代码使用了一个我无法更改的 API,在我无法更改
这是我的测试程序: #include #pragma GCC diagnostic ignored "-Wcast-qual" static void proc(char *buf) { p
static char buf[8]; void foo(){ const char* ptr = buf; /* ... */ char* q = (char*)ptr; }
有没有办法让我使用 c++11 关键字 alignas装饰函数get() .在某些情况下,我知道 get() 返回的缓冲区将包含正确对齐的浮点缓冲区。 代码: $ cat c.cxx extern c
我是一名优秀的程序员,十分优秀!