首先我们谈谈gcc / linux(x86,amd64)和c99。
以下是代码:
#include <stdint.h>
void f(void *p)
{
uint32_t *num = p;
*num = 17;
}
int main()
{
char buf[8] __attribute__ ((aligned (8)));
f(&buf[3]);
}
问题是UB?
一方面英特尔CPU允许不对中访问, 从另一只手我发现了这个: http://www.uclibc.org/docs/psABI-i386.pdf http://www.x86-64.org/documentation/abi.pdf 并且它们都提到4字节对齐4字节整数。
所以即使它编译并且工作正常它仍然是UB? 因为gcc认为“uint32_t *”指针的值指向 4字节对齐的地址, 并且毫不犹豫地使用“f”函数中的“SSE”?
gcc维护者认为这样的代码是“未定义的代码”: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66194
答案 0 :(得分:1)
编译和链接很好意味着什么,在运行时发生未定义的行为。就C标准而言,代码可能会也可能不会调用UB。
6.3.2.3/7:
指向对象类型的指针可以转换为指向a的指针 不同的对象类型。如果结果指针不正确 对于引用的类型,行为是未定义的。
术语“正确对齐”取决于CPU架构。如果您的CPU没有对齐限制,则uint32_t指针将被视为正确对齐,然后您将没有UB。
如果CPU允许错位访问,但会导致代码效率降低,那么你也没有UB。
但如果CPU不支持错位访问,则代码为UB。
答案 1 :(得分:1)
x86和x64指令集都允许未对齐访问,而不会导致未定义的行为,但SIMD扩展指令集除外。
x86 / x64中的代码问题是由于别名冲突而调用未定义的行为。由于您已使用gcc
扩展程序,因此可以使用-fno-strict-aliasing
停用别名规则。