C语言中结构体指针解引用时访问的是哪块内存?
结构体指针解引用的实际行为说明
你的输出和预期不符的核心原因是代码存在未定义行为,和指针解引用的本身逻辑无关。
核心概念梳理
- 你对
a和&(a->val)的理解是完全正确的:a保存的是malloc分配的内存块首地址,C标准明确规定结构体的首地址与其第一个成员的地址完全一致,不存在内存偏移,所以前两个打印值相同是符合预期的。 - 对结构体指针
a做解引用操作(即*a)时,得到的是**a指向的整个struct Node类型的结构体对象本身**,它的类型是struct Node,既不是指针类型,也不是结构体的某个成员,更不是地址值。
你代码的错误点
printf的%p格式符严格要求传入参数必须是void*类型的指针,你传入*a属于参数类型不匹配,是标准明确规定的未定义行为:
你打印出来的第三个值00000000001C0150根本不是什么有效内存地址,只是malloc分配的内存里没有初始化的随机垃圾值——因为你没给a->val赋初值,这块内存里残留的旧数据被printf错误解析成了指针值输出,完全不具备参考意义。
正确的验证方式
你可以用下面的代码验证结构体指针解引用的实际行为:
#include <stdio.h> #include <stdlib.h> struct Node { int val; }; int main() { // 注意纯C环境中struct类型声明变量需要带struct关键字,C++环境可以省略 struct Node* a = (struct Node*) malloc(sizeof(struct Node)); a->val = 999; // 给成员赋值,消除未初始化的垃圾值 printf("malloc分配的内存块首地址(即指针a存储的值): %p\n", (void*)a); printf("结构体第一个成员val的地址: %p\n", (void*)&(a->val)); printf("解引用a后访问结构体val成员的值: %d\n", (*a).val); // 验证:结构体指针的->运算符本质就是(*ptr).member的语法糖 printf("通过a->val访问的值和(*a).val完全一致: %d\n", a->val); free(a); return 0; }
运行这段代码你会看到前两个地址完全相同,后两个值完全相同,符合结构体指针的访问逻辑。
补充说明:如果你想拿到结构体首地址对应的第一个成员值,直接用
a->val即可;如果你想拿到第一个成员的指针,用&(a->val)或者(int*)a都可以,两者的值完全相等。
内容的提问来源于stack exchange,提问作者litr
相关产品推荐
相关产品推荐

