C语言数组字符串初始化问题
char s[5]="abc";
这两个的结果是一样的吗
还是第一个只是s【0】是字符串abc ? 展开
你申请数组空间后,内存中存放字符的顺序是:
str1[0],str1[1],str1[2],str1[3],str1[4],str2[0],str2[1],str2[2],str2[3]
当输入字符串是:abc 123时,存储的数据str1[0]~str1[4],str2[0]~str2[3]为:
‘a','b','c',0,xx,'1','2','3',0
其中,xx表示一个不关心的任意值,也就是说输入字符串"abc"需要占用4个字节的存储空间
当输入字符串1为"abcde"时,存储的数据为:'a','b','c','d','e',0,xx,xx,xx
字符串末尾的0已经超出了str1开设的存储空间而存放到了str2[0]位置
接着再输入字符串"1234"时,str2[0]的str1字串的结尾符被字符'1'覆盖,
存储的数据为:'a','b','c','d','e',’1‘,’2‘,’3‘,’4‘,0
而且由于str2输入字符数为4个其占用空间也超出了str2的空间范围,那么上边存储的0值也不知道覆盖了什么变量的位置,导致其他变量的值被冲掉了。
当执行printf("%s\n",str1);时,printf从str1[0]开始输出的字符串(遇0结束输出)为abcde1234
当执行printf("%s\n",str2);时,printf从str2[0]开始输出的字符串(遇0结束输出)为1234
所以你输入的第1个字符串字符数少于5时,存储不会溢出,多于4个时,末尾的0就会被输入的str2所覆盖而失效,且多于5的字符也会被覆盖。scanf并不能保证输入字符的长短不会溢出,你应当在设计程序时考虑到这点,预先定义足够的字符串保存空间或用其他方法来避免这个问题的出现。
%s的打印,是以结束符为标志的
两点要理解
1、字符串和字符数组是不一样的两个东西
虽然都是这么定义,但是字符串需要\0这个结束符,字符数组不需要
2、变量的内存模型
程序运行时,要申请内存来保存变量的数据,并且是紧挨着的,具体顺序我忘记了,有的编译器可能不同
按你的程序,str1在前,str2在后,并且是紧挨着的,str1 5个内存空间,紧挨着str2 4个空间,后面可能还要空间没有使用
你输入abcde后,占用6个空间,吧str2的一个空间占用了,这里是不检查越界的
接着输入abcd,把str1的结束符覆盖掉,并且也是越界,因为str2是4个字符空间,结束符要占一个,是5个空间,把内存中str2后面的一个内存写入结束符,如果后面还有变量的话,程序会出错
这样打印%s时,str1检查结束符是str2后面的结束符,所以是abcdeagcd,str2是abcd
除了char s[5]="abc"; ,还有char s[5]={'a','b','c'};这两种写法。
两种写法的区别是 char s[5]="abc"; 在后门自动加一个0,习惯上称之为“字符串数组”;而char s[5]={'a','b','c'};不会再结尾加0,一个称之为“字符数组”。
二、s【0】是只能存放一个字符的存储空间,只能存放一个字符,不可能存放字符串abc 。
如有疑问请留言。
但是如果你这样定义数组
int a[10]={1,2};
那么有些编译器会把后面的项初始化为0,但也不能保证所有的编译器都会这样做,所以不建议这样做,尽量对数组进行初始化。
s[0]打印的是第一个字符,即'a'
希望对你有用