在我之前提出的与按位运算有关的问题中,有人告诉我,如果char
数组未与int
地址对齐,则使用int
指针访问char
数组(一次对较大的字节块进行操作)的代码可能会出现问题。
然后,在C中思考,我想知道当malloc
为未知类型分配内存时会发生什么。例如,如果我执行void *p = malloc(sizeof(int));
,我是否获得有效的字符/整数/长对齐内存地址?
根据 SO 中引用该标准的一些答案,"返回的指针应适当对齐,以便可以转换为任何完整对象类型的指针"。
因此,我知道在这种情况下我可以毫无问题地从char*
到int*
:
char *p = malloc(16);
int *n = (int*)p; // use n a base of an array of 16 / sizeof(int) ints
正确吗?
转到C++,标准中似乎出现了相同的规则。那么,如果我这样做,我是否可以假设没有对齐风险?
char *p = new char[16];
int *n = reinterpret_cast<int*>(p);
,C 和 C++ 中的malloc
以及 C++ 中的 new char[N]
都返回最大对齐的指针。对齐方式是 或 max_align_t
的类型。
在这方面有一个错误,在 GCC-4.9 中修复。只需包含并使用不带std::
前缀的::maxalign_t
。
对过度对齐类型(即对齐方式大于上述最大值的类型)的支持是实现定义的。 例如,Posix 提供了posix_memalign
来分配具有更大对齐方式(例如页面对齐)的内存。
char* p = new char[16];
int* n = reinterpret_cast<int*>(p);
这很好,但更好的是:
char* p = new char[16];
int* n = static_cast<int*>(static_cast<void*>(p));
或者,您可以使用 C++ 的operator new
,如下所示:
void* p = operator new(16);
int* n = static_cast<int*>(p);
少了一个static_cast
。
malloc
返回一个地址,该地址对于 C 中的任何基类型都正确对齐。这意味着它可以安全地转换为所有这些类型(int
、长、double
等)的指针。