C++二维数组名解引用*a输出字符串而非地址的疑问
C++二维char数组输出疑问解答
问题复现
测试代码如下:
#include <iostream> using namespace std; int main() { char a[][6] = { "hello", "hii" }; cout << a << ", " << *a << ", " << **a; return 0; }
实际运行输出:
0x7ffd1f44a20c, hello, h
已知基础规则:二维数组的数组名a指向其首个一维数组(本例中为存储"hello"的长度为6的char数组),*a指向该一维数组内的元素,**a返回*a指向的具体值。
存在两种矛盾的推理:
- 推理1:现有输出正确:
a指向的值为"hello",因此*a会打印a指向的值 - 推理2:现有输出错误:
*a本身指向一维数组内的首元素,应当输出a所指向一维数组首元素对应的内存地址,预期输出应为0x7ffd1f44a20c, h的地址, h
核心结论
现有输出完全正确,推理2的偏差来自于忽略了cout对char*类型的特殊处理逻辑。
逐段拆解三个输出项的实际行为:
- 第一个输出项
a
二维数组名在表达式中会隐式转换为指向其首个元素的指针,此处a的首个元素是长度为6的char数组,因此a的实际类型为char (*)[6](指向长度为6的char数组的指针)。cout输出非char类型的指针时,默认打印指针存储的内存地址,因此第一个值是数组首地址的十六进制表示,符合预期。 - 第二个输出项
*a
对char (*)[6]类型的指针解引用,得到类型为char[6]的一维数组,该数组传入cout时会再次隐式转换为指向数组首元素的指针,类型为char*。cout针对char*类型做了专门的重载:不会打印指针本身存储的地址值,而是从指针指向的内存位置开始逐字符输出,直到遇到字符串结束符\0为止,因此此处直接输出字符串hello,而非首元素的地址。
如果需要打印*a对应的首元素内存地址,只需要将其强制转换为通用指针类型即可,例如写cout << (void*)*a,此时输出的地址值和第一个输出的地址数值完全相同(二维数组首地址、首元素一维数组的首地址、一维数组首元素的地址三者数值一致,仅指针类型不同)。 - 第三个输出项
**a
对char*类型的指针再次解引用,得到单个char类型的值,即数组首元素字符'h',cout直接打印该字符,符合预期。
可以做个简单对照验证:把char数组换成int数组测试,例如定义int b[][2] = {{1,2}, {3,4}},此时cout << *b会直接输出内存地址——因为*b的类型是int*,cout没有针对int*的特殊字符串打印逻辑,会走默认的指针地址输出规则,也能侧面印证上述逻辑。
内容的提问来源于stack exchange,提问作者yash
相关产品推荐
相关产品推荐

