我无法解释这个程序的执行行为:
#include <string>
#include <cstdlib>
#include <stdio.h>
typedef char u8;
typedef unsigned short u16;
size_t f(u8 *keyc, size_t len)
{
u16 *key2 = (u16 *) (keyc + 1);
size_t hash = len;
len = len / 2;
for (size_t i = 0; i < len; ++i)
hash += key2[i];
return hash;
}
int main()
{
srand(time(NULL));
size_t len;
scanf("%lu", &len);
u8 x[len];
for (size_t i = 0; i < len; i++)
x[i] = rand();
printf("out %lu\n", f(x, len));
}
Run Code Online (Sandbox Code Playgroud)
因此,当使用带有gcc的-O3编译并使用参数25运行时,它会引发段错误.没有优化它工作正常.我已经对它进行了反汇编:它正在进行矢量化,并且编译器假定 …
2020 年 12 月 11 日更新:感谢@“一些程序员老兄”在评论中提出的建议。我的根本问题是我们的团队正在实现一个动态类型存储引擎。我们分配了多个16 对齐的char array[PAGE_SIZE] 缓冲区来存储动态类型的数据(没有固定的结构)。出于效率原因,我们不能执行字节编码或分配额外的空间来使用memcpy.
既然已经确定了对齐方式(即16),剩下的就是使用指针的强制转换来访问指定类型的对象,例如:
int main() {
// simulate our 16-aligned malloc
_Alignas(16) char buf[4096];
// store some dynamic data:
*((unsigned long *) buf) = 0xff07;
*(((double *) buf) + 2) = 1.618;
}
Run Code Online (Sandbox Code Playgroud)
但是我们的团队对这个操作是否是未定义的行为存在争议。
我已经阅读了许多类似的问题,例如
但是这些和我对C标准的解释不同,我想知道是不是我的误解。
主要的混淆是关于C11的第6.3.2.3 #7节:
指向对象类型的指针可以转换为指向不同对象类型的指针。如果结果指针未正确对齐 68) 引用类型,则行为未定义。
68) 通常,“正确对齐”的概念是可传递的:如果指向类型 A 的指针与指向类型 B 的指针正确对齐,而指向类型 …