解决方案之一经常出现在有关如何确定 void *
是否为多个帖子中的解决方案指向对齐内存涉及强制转换 void 指针。也就是说我得到了 void *ptr = CreateMemory()
现在我想检查 ptr
是否指向内存是某个值的倍数,例如 16。
参见How to determine if memory is aligned?其中提出了具体的主张。
A pointer p is aligned on a 16-byte boundary iff ((unsigned long)p & 15) == 0.
这篇文章中出现了类似的解决方案。 How to check if a pointer points to a properly aligned memory location?
有人可以澄清一下,这个选角是如何进行的吗?我的意思是,如果我有一个 void *ptr = CreateMem();
,在我看来 (unsigned long)(ptr)
会给我指针本身重新解释为 unsigned long
。为什么这个重新解释的 void 指针的值会对指向的内存的对齐产生影响?
编辑:感谢所有有用的评论。请再多忍耐一下。也许一个简化的例子会帮助我更好地理解这一点。
#include <iostream>
using namespace std;
struct __attribute__((aligned(16))) Data0 {
uint8_t a;
};
struct Data1 {
uint8_t a;
};
int main() {
std::cout<<sizeof(Data0) << "\n"; //< --(1)
std::cout<<sizeof(Data1) << "\n";
Data0 ptr0[10];
Data1 ptr1[10];
std::cout<<(unsigned long) (ptr0 + 1) - (unsigned long) ptr0 << "\n"; //< --- (2)
std::cout<<(unsigned long) (ptr1 + 1) - (unsigned long) ptr1 << "\n";
return 0;
}
迄今为止,我总是将对齐内存解释为具有以下两个要求。 sizeof()
应返回指定大小的倍数(参见条件 (1))。当递增指向对齐结构数组的指针时,步幅最终也将是指定大小的倍数(参见条件(2))。
所以我有点惊讶地看到对ptr0
的实际值有第三个要求。以及。或者我可能完全误解了这一点。 ptr0
所指向的内存会吗?在上面的例子中被认为是对齐的,而对于 ptr1
则不然?
当我打字时,我意识到我实际上并不理解对齐内存本身的含义。由于我主要在分配 cuda 缓冲区时处理这个问题,因此我倾向于将其与数据结构所需的某种填充相关联。
考虑第二个例子。 aligned_alloc
的那个。 https://en.cppreference.com/w/c/memory/aligned_alloc
Allocate size bytes of uninitialized storage whose alignment is specified by alignment.
我不知道如何解释这一点。比如说,我做了一个void *p0 = aligned_alloc(16, 16 * 2)
, p0
指向的内存有什么不同?与 p1
相比哪里std::vector<char> buffer(32); char *p1 = buffer.data()
.
最佳答案
(unsigned long)(ptr)
将指针转换为无符号整数会返回指针的内存地址。
p & 15
等价于 p % 16
,即除以 16 的余数。如果为 0,则表示内存对齐为多个共 16 个。
((unsigned long)(ptr) & 15) == 0
如果内存与 16 的倍数对齐,则返回 true。
uintptr_t
是此类转换的更好类型,因为它应该更加与平台无关。
关于c++ - 强制转换 void 指针以检查内存对齐情况,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57968560/