结构体指针->运算符疑问:两次printf输出值不同原因求解
结构体指针链式访问的数值解释
让我一步步帮你拆解这个问题,先从代码的结构和内存布局说起~
首先贴出完整可运行的代码:
#include <stdio.h> struct S { int Var; struct S *Str; }; int main(void) { struct S S[] = { { 8, NULL }, { 4, &S[0] }, { 2, &S[1] } }; printf("%d\n", S[2].Str->Str->Var); // 输出8 printf("%d\n", S[2].Str->Var); // 输出4 return 0; }
一、明确结构体数组的初始化内容
你定义的数组S包含3个struct S实例,初始化后每个实例的成员值非常清晰:
S[0]:Var = 8,Str = NULL(空指针)S[1]:Var = 4,Str = &S[0](指向数组第一个元素S[0])S[2]:Var = 2,Str = &S[1](指向数组第二个元素S[1])
二、拆解第一个输出:S[2].Str->Str->Var = 8
我们逐层解析这个链式访问的逻辑:
S[2].Str:取出S[2]的Str成员,结果是&S[1](一个指向S[1]的指针)S[2].Str->Str:通过指针访问S[1]的Str成员,结果是&S[0](指向S[0]的指针)S[2].Str->Str->Var:通过指针访问S[0]的Var成员,直接得到8——这就是第一个输出的来源。
三、拆解第二个输出:S[2].Str->Var = 4
同样逐层拆解:
S[2].Str:依然是&S[1](指向S[1]的指针)S[2].Str->Var:通过指针访问S[1]的Var成员,直接得到4——这就是第二个输出的原因。
关于你提到的“指针占用8字节、地址间隔8字节”的疑问
你可能混淆了结构体实例的内存大小/数组元素的地址间隔和结构体成员的偏移量:
- 在64位系统中,指针确实占8字节,
int通常占4字节。由于内存对齐规则,每个struct S实例的大小会是16字节(Var后面会填充4字节空白,以对齐到8字节的指针边界),所以数组S中S[0]、S[1]、S[2]的地址间隔是16字节。 - 但
Var是结构体的第一个成员,它的内存偏移量永远是0。不管结构体整体多大,通过指针访问->Var时,都是直接取指针指向地址的前4字节(对应实例的Var值),这和指针本身的大小、数组元素的地址间隔没有关系。
内容的提问来源于stack exchange,提问作者Noel Nosse
相关产品推荐
相关产品推荐

