c++ - 强制转换 void 指针以检查内存对齐情况

标签 c++ pointers c++17

解决方案之一经常出现在有关如何确定 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/

相关文章:

c++ - 带有 std :out_of_range issue (C++) 的简单密码

c++ - Visual Studio 2015 - 编译器警告(2 级)C4146

C++ 何时在模板定义中衰减

c++ - 如何使用\b删除换行符

c++ - 在 C++ 中迭代 std::map 的键/值

C++ 指向对象的类成员的指针

arrays - 通过在 c 中迭代打印字符

c++ - (DWORD)、*(DWORD*) 和 (DWORD*) 之间有什么区别?

c++ - 如何在 Visual Studio 中启用 C++17 编译?

c++ - 标准对 char 数组作为模板参数有什么看法?