C语言中数组名与数组首元素的区别?为何地址相同输出不同?
为什么数组名和首元素地址相同,但printf输出结果却不一样?
这问题问得特别好!很多刚学C的朋友都会在数组名的本质上绕晕,咱们一步步拆解清楚。
首先要明确一个核心规则:在大多数表达式场景下,数组名会被隐式转换为指向数组首元素的指针——这就是你看到&str1和&str1[0]打印出相同地址数值的原因,它们指向的是同一块内存的起始位置。但关键是:这两个指针的类型完全不同!
咱们拿你的代码片段来分析:
char str1[] = "Hello"; printf("%d %d %s %c\n", &str1, &str1[0], str1, str1[0]); // 输出:-476114470 -476114470 Hello H
1. 地址数值相同,但类型不同
&str1的类型是char (*)[6]:这是一个指向长度为6的char数组的指针(因为str1是char[6]类型,字符串"Hello"末尾会自动补'\0',所以总长度是6)。&str1[0]的类型是char *:这是一个指向单个char的指针,也就是数组首元素的地址。
当用%d打印时,printf只读取地址的数值,不管它的类型是什么,所以两个地址的起始数值完全一致,输出自然相同。
2. printf格式符决定了参数的解析方式
printf是根据你给出的格式符来解析传入的参数的:
- 当你用
%s时,它要求参数是char *类型。此时你传入的str1会被隐式转换成指向首元素的char *指针,printf就从这个地址开始逐字符打印,直到遇到'\0',所以输出完整的"Hello"。 - 当你用
%c时,它要求参数是单个char类型。str1[0]就是数组的第一个元素,也就是字符'H',所以直接输出这个字符。
3. 再举个例子区分数组名和指针
你可以试试运行这段代码,更直观地看出差异:
char str1[] = "Hello"; char *p = str1; printf("sizeof(str1) = %zu\n", sizeof(str1)); // 输出6,整个数组的大小 printf("sizeof(p) = %zu\n", sizeof(p)); // 输出4或8,指针的大小(取决于系统)
这里sizeof(str1)计算的是整个数组的字节数,而不是指针的大小,这就是数组名没有被转换为指针的特殊场景之一(还有&str1、typeof(str1)等场景也不会转换)。
内容的提问来源于stack exchange,提问作者La Murga




