C语言中printf的%p处理数组与指针的行为差异疑问
数组名与地址输出的疑惑解答
问题描述
在第一个printf中,输出的是arr的地址,这符合预期。但第二个printf也输出了相同的地址,它难道不应该输出arr指向的“值”(即地址0)吗?
代码示例
char * arr[2]; char ** p; int main(){ p = arr; printf("%p\n",&arr); printf("%p\n",arr); printf("%p\n",&p); printf("%p\n",p); /* OUTPUT 0x10aa71010 0x10aa71010 0x10aa71020 0x10aa71010 */ }
核心原因解析
- 数组名的隐式转换规则:C语言中,数组名
arr在多数表达式场景下会自动转换为指向数组第一个元素的指针(即&arr[0])。此时arr的类型从char*[2](数组类型)转为char**(指针类型),但它的地址值和数组的起始地址完全一致——因为数组的起始位置就是第一个元素的起始位置。 &arr的本质:&arr是取整个数组的地址,类型为char*(*)[2](指向数组的指针),它的地址值同样是数组的起始地址,所以和arr转换后的指针值打印出来完全相同。两者的区别仅在于类型和指针步长:对&arr做自增操作会跳过整个数组的大小,而对arr转换后的指针自增只会跳过一个元素的大小。- 关于“输出arr指向的值”的误解:
arr本身是数组,不是指针,它不“指向”任何值——数组是一块连续内存,用来存放元素。你误以为它会输出0,是混淆了数组名和指针的概念。数组中的元素arr[0]、arr[1]才是char*类型的指针,由于arr是全局数组,元素会被默认初始化为0,若要输出这个值,需要访问数组元素而非数组名本身。
验证方法
如果要输出数组第一个元素存储的地址(也就是你以为的“arr指向的值”),修改代码中的printf语句:
printf("%p\n", *arr); // 等价于 printf("%p\n", arr[0]);
此时会输出0x0,这才是你想要的结果。
内容的提问来源于stack exchange,提问作者user18503064
相关产品推荐
相关产品推荐

