为何直接打印char数组可输出内容,int数组却显示乱码?
先弄明白printf的%s是怎么干活的
用printf("%s", 指针)的时候,它只认一条死规则:
- 把传入的指针当成
char*用,从指向的内存地址开始,挨个读字节,每个字节按ASCII码转成字符输出 - 读到值为
0的字节(也就是'\0'空字符)就立刻停
你的char数组能输出swap其实是碰运气
你写的char jane[]={'s','w','a','p'},这种用单个字符初始化的方式,编译器不会自动在数组末尾加'\0'——这个数组就4个字节,内存里存的就是s、w、a、p对应的ASCII码,后面没终止符。
能完整输出swap纯粹是巧合:数组后面的栈内存刚好有个值为0的字节,printf读到这个0就停了。换个环境跑,大概率会在swap后面蹦出一堆乱码,这属于C语言的未定义行为——标准没说这种情况该咋样,全看当时的内存状态。
要是改成char jane[]="swap"(用字符串字面量初始化),编译器会自动在末尾补'\0',这时候用%s打印才是靠谱的、符合预期的操作。
int数组打印出乱码的原因
当你把int mane[]={2,5,6,7}传给printf("%s", mane)时,数组名mane会退化成指向第一个int元素的指针(int*类型)。但printf的%s不管这些,直接把这个指针当成char*来处理——它会从数组首地址开始,逐个字节读,然后按ASCII码转成字符。
拿常见的32位int、小端模式来说:
- 数字
2存在内存里是0x02 0x00 0x00 0x00(4个字节) - 数字
5是0x05 0x00 0x00 0x00
这些字节里,0x02、0x05都是不可打印的控制字符,剩下的全是0x00(也就是'\0')。所以printf会先输出0x02对应的乱码(比如一个小方块或者奇怪符号),然后读到第一个0x00就停,看起来就是乱码。
要是你直接用printf("%d", mane),打印的是数组首地址的十进制值;用printf("%p", mane)则是首地址的十六进制形式,都不是数组里的数值。要打印int数组,必须循环遍历每个元素,挨个输出。
内容的提问来源于stack exchange,提问作者Swapnil Mishra

