C语言指针指向疑问:为何pa的值不等于变量a的地址?
问题核心原因:函数传参的局部变量副本
你的疑惑根源在于函数参数的按值传递机制,以及你在var_print函数中混淆了两个完全独立的a变量:
1. 两个a的本质区别
代码里存在两个毫无关联的a变量:
- 主函数
main中的int a = 0:属于main栈帧的局部变量,pa = &a让指针pa指向的是这个变量的地址。 var_print函数参数中的int a:调用var_print时,从main的a拷贝过来的局部变量,属于var_print的栈帧,和main的a地址完全不同。
你在var_print中打印的&a,是这个局部参数a的地址,而非main里a的地址;但pa参数的值是从main的pa拷贝过来的,仍然指向main里的a。这就是为什么pa的值和&a不相等——它们指向的是两个完全不同的内存位置。
2. 指针差值的逻辑解释
指针相减的结果是以指向类型的大小为单位的(比如int*相减,单位是sizeof(int),通常为4字节)。由于栈的生长方向通常是从高地址向低地址,main的栈帧位于更高的内存区域,var_print的栈帧在更低的地址区域:
main里的a地址(pa的值)高于var_print里局部a的地址(&a),所以pa - &a的结果是正数,数值等于两个地址的字节差除以sizeof(int)。- 当你新增
pa2变量时,main的栈帧布局发生变化,main里a的地址和var_print局部a的地址的字节差改变,导致差值数值变化,但本质逻辑不变。
验证方法:修改代码区分变量
把var_print的参数名改成和main不同的名字,就能直观看到区别:
void var_print(int a_main, int b_main, int *pa, int *pb, long int dist) { printf("Variable\tValue\t\tAddress\t\t\tPoints to...\t\t&var - pointer-to-var\n\n"); printf("func param a\t%d\t\t%p\n", a_main, &a_main); // 函数参数的地址,和main的a无关 printf("*pa\t\t%d\t\t%p\t\t%p\t\t%d\n", *pa, &pa, pa, (int)(pa - &a_main)); printf("func param b\t%d\t\t%p\n", b_main, &b_main); printf("*pb\t\t%d\t\t%p\t\t%p\t\t%d\n", *pb, &pb, pb, (int)(&b_main - pb)); printf("dist\t\t%ld\t\t%p\n", dist, &dist); }
如果想要在var_print中打印main里a的地址,需要传递&a作为指针参数,而非传递a的值。比如修改函数参数为int *a_ptr,调用时传&a,就能直接访问main里a的地址。
内容的提问来源于stack exchange,提问作者Haandrea
相关产品推荐
相关产品推荐

