我创建了以下代码来理解offsetof()和container_of()宏。这里printf()显示两个不同的地址而不是相同的地址。我做错了什么?
#include <stdio.h>
#include <stddef.h>
typedef unsigned char Byte;
#define container(ptr, type, member) \
({ \
(type *)((Byte *)ptr - offsetof(type, member)); \
})
typedef struct
{
size_t size;
void *block;
}Header;
int main()
{
void *ptr = malloc(3);
Header *pHdr = container(ptr, Header, block);
printf("%p %p\n", ptr, pHdr->block);
return 0;
}
答案 0 :(得分:1)
看起来代码正在尝试检查/演示malloc实现的内部工作方式。您的container
宏正在运行,问题是您的Header
结构定义不正确:
typedef struct
{
size_t size;
void* block;
} Header;
这意味着malloc
保持内存中分配的大小,后跟指向块的指针。这不准确 - 您假设不存在额外的间接级别。您的代码最终会将数据块的内容解释为void*
。由于你还没有初始化那个记忆,你会发现那里发生了什么(根据你给出的值,看起来你可能会看到指向下一个空闲区块的指针 - 当你malloc(0)
你&#39时;不允许写入数据块,因此实现可能会使用它 - 例如,请参阅glibc malloc implementation中的struct malloc_chunk
。
更正确的结构定义(适用于clang-503.0.40 / LLVM 5.1和VC 2012)将是:
typedef struct
{
size_t size;
char block[0];
} Header;
您还需要更改printf
以打印block
的地址:
printf("%p %p\n", ptr, &pHdr->block);
当然,请注意,不能保证每个malloc
实现都会在块之前实际存储块大小,因此这可能并不总是有效。