You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言指针打印疑惑:为何a与p、p2与pp2地址相同?

C语言数组名与指针变量地址相同的原因解析

问题代码

int main() {
    int a[] = { 1, 2, 3, 4, 5 }; // a指向a[0]的地址
    int *p = a; // p与a指向同一地址
    int **pp = &p; // 指向p

    int *p2[] = { a, a+1, a+2, a+3, a+4 }; // 指向a
    int **pp2 = p2; // 与p2指向同一地址

    printf("  a: %p,         *a: %p\n", a, *a);
    printf("  p: %p,         *p: %p\n", p, *p); 
    printf(" pp: %p,        *pp: %p,        **pp: %p\n",        pp,  *pp,  **pp);
    printf(" p2: %p,        *p2: %p,        **p2: %p\n",        p2,  *p2,  **p2);
    printf("pp2: %p,       *pp2: %p,       **pp2: %p\n",       pp2, *pp2, **pp2);
    
    return 0;
}

编译运行方式

gcc main.c -o main
./main

运行输出

a: 0061FF04,         *a: 00000001
  p: 0061FF04,         *p: 00000001
 pp: 0061FEEC,        *pp: 0061FF04,        **pp: 00000001
 p2: 0061FEF0,        *p2: 0061FF04,        **p2: 00000001
pp2: 0061FEF0,       *pp2: 0061FF04,       **pp2: 00000001

疑惑点

a和p的打印地址相同(0061FF04),p2和pp2的打印地址相同(0061FEF0),这一现象无法理解。


解答

1. 为什么a和p的打印地址相同?

  • 数组名a在绝大多数表达式场景中会自动隐式转换为指向数组首元素的指针,也就是&a[0]。当你用%p打印a时,实际输出的是数组第一个元素的内存地址。
  • 指针变量p被赋值为a,本质是接收了a转换后的指针值(即&a[0]),所以p存储的内容就是数组首元素的地址。打印p时,输出的就是这个存储的地址值,自然和a的打印结果一致。
  • 注意:a是数组类型,不是指针变量,它没有自己独立的内存地址(或者说&a是整个数组的地址,和&a[0]数值相同但类型不同);而p是实实在在的变量,有自己的内存地址,你可以添加printf("&a: %p, &p: %p\n", &a, &p);验证,两者地址完全不同。

2. 为什么p2和pp2的打印地址相同?

  • p2是一个指针数组,数组名p2同样会在表达式中隐式转换为指向数组首元素的指针,也就是&p2[0]。
  • 二级指针pp2被赋值为p2,也就是接收了p2转换后的指针值(&p2[0]),所以打印pp2时,输出的就是这个地址,和p2的打印结果一致。
  • 同理,p2是数组类型,pp2是指针变量,&p2和&pp2的地址完全不同,可通过打印验证。

额外提示:代码中的未定义行为

你代码中用%p打印*a、*p、**pp等int类型的值是错误的,%p格式符要求对应参数是void*类型。这些值是整数,应该用%d打印,当前输出的00000001是把整数1强制当成地址解析的结果,属于未定义行为,建议修正。


内容的提问来源于stack exchange,提问作者user1132252

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 03:42:50