问一个C语言字符输出的问题

代码:
#include<stdio.h>
main(){
char a[6]={'a','b','c','d','e','f'};

printf("%s\n",a);
}
输出结果:
abcdef@

为什么最后有一个@?
还有char b[6]={"abcdef"};这句定义为什么会出错?我把最后一个字符'f'去掉后就正确了,然后输出b结果为:abcde,没有@,为什么,这两种定义有什么不同吗?

第二个问题。

"abcdef"是在定义字符串,注意双引号""。字符串会自动在末尾加一个\0。其含义相当与数值编号中的0,即ASCII编码0的不显示的符号。它作为字符串的结尾。
abcdef这几个字母是6个字节,加结尾1个字节。共7个字节。超过变量的范围了。
也就是说这个变量实际上只能有5个字母。所以去掉任何一个字母它都能编译通过。

第一个问题
这应该与printf("%s\n",a);中的%s有关。%s的含义是输出字符串中的字符直至字符串中的空字符(字符串以'\0‘结尾,这个'\0'即空字符)
char a[6]={'a','b','c','d','e','f'};

虽然是在定义六个字母,但是printf("%s\n",a)把它当成了字符串对待,字符串要以\0结尾。追问

那什么第一种定义不会超出而第二种会超出呢?

追答

a[6]定义了六个字节的存储空间。

字符串需要有个\0结尾,它本身就占一个字节。那就剩5个字节了。
{'a','b','c','d','e','f'}和{"abcdef"}都是6个字节,而\0就成了第7个字节了。明显超过了变量的定义范围了。

追问

我明白了,第一种初始化只有元素数小于数组长度时才会自动补'\0',而第二种是强制的最后一个字符必定是'\0'。那么问题来了,printf("%s\n",a);是如何判断字符数组结束的呢?最后一个@我还是不明白,他肯定是扫描了的,然后以此作为结束标志(抱歉问的有点多,我提高点悬赏吧,谢谢)

追答

printf("%s\n",a),这个%s就说明变量a是字符串。只要是字符串它就应该找\0,只要遇到\0它就不会显示后续的字符了。

你可以用下面的例子看看。
char a[6]={'a','\0','d','f','A','c'};

至于@可能与函数栈结构有关系。具体不清楚。

温馨提示:答案为网友推荐,仅供参考
第1个回答  推荐于2016-05-13
printf在输出字符串的时候是到'\0'为止,
char a[6]={'a','b','c','d','e','f'};没有'\0',因此多输出了些内容,直到碰到'\0'。
任何字符串在编程中都应该考虑到'\0'这个隐藏着的字符。

char b[6]={"abcdef"};

报错的原因是它的实际长度为7,因此不能放入只有长度为6的字符数组中。
原因是"abcdef"的结尾隐藏了一个'\0',它的真实形态为"abcdef\0"
所以当以这样形式【char b[6]={"abcde"};】赋值时,既不会报错输出也正常。追问

我不明白的是为什么会输出@(不是随机,今天我又试了几次还是@),char a[6]={'a','b','c','d','e','f'};这种初始化方法没有包含'\0'又是怎样判断输出结束的呢?

追答

这就是编译器不同结果也不同。

我的编译器是MinGW GCC


下图是我打得代码和结果:

本回答被提问者采纳
第2个回答  2015-09-27
字符数组以'\0'结束,所以char a[6]实际上你只能放5个字符,剩下一个放'\0',一般系统会自动做这件事。
如果存放6个字符,没有空间放'\0'的话,以字符串%s输出字符数组的话,将会一直输出到找到'\0'为止,也就是会读取紧邻'f'的下一个位置,而这个位置的值是未知的,这一次的@ 下一次可能是& 任何其他内容。追问

那什么第一种定义不会超出而第二种会超出呢?

追答

因为严格意义上来说,char b[6]是可以定义为{'a','b','c','d','e','f'}的,因为他是字符数组,0-5分别存放a-f,可以通过编译。只是不能再作为字符串%s使用。
而char b[6]={"abcdef"},明确指出为存放字符串"abcdef"于字符数组b中,但是空间不够用,编译器会报错的。

相似回答