为什么 r 数组一开始的长度为2?
最后长度又为什么变成了18?
而且值为啥是987654321123456789?
主要就是三个问题:
1、所有内存申请的时候,只是分配空间,但不保证这块空间的内容是什么,也就是内容是随机的。
不管数局部变量从栈上申请,还是有malloc函数从堆上申请,都一样
2、strlen这个函数求值,是遇到\0
才结束,所以如果你想求一个字符串的长度,一定要保证这个字符串是以\0
结尾的,否则strlen会一直向后计算非\0
字符的数量
3、printf函数也是遇到0结尾,其实记住了所有字符串操作都要保证结尾有\0
所以对你的代码:
1、“123456789”这种字符串的定义,其实最后默认包含了\0
,所以其实一共有10个字符,可以用sizeof(s)来看其大小
2、r[9]的定义为了最后一个字符存储\0
,其实实际能够存储的字符数只有8个
3、你的for循环对r这个数组进行了9次赋值,最后一个r[9]=9,导致这个数组最后一个字符也不是\0
,所以用strlen求长度时,是难以预料到,就看这块内存后面的内容了。
4、同样的printf是一样的问题,没有遇到\0
就一直打印
strlen(s)
纯粹计算从 s
位置到第一个 '\x00'位置的长度,因此只能用于以 '\x00' 结尾的字符串,而你的 r[9]
没有。
printf("%s", s)
同理。
实际上,char s[] = "123456789"
会自动编译成 'x00' 结尾,因此,s
在运行时占用 10 个字节,像这样 "123456789\x00".
这段程序应该每运行一次的结果都不完全一致。具体原因是这样:
char s[] = "123456789", r[9];
相当于定义了s数组,具体存到内存中占用了10个连续存储单元,其实1-9分别占用一个字节,最后系统还默认添加了00000000到最后一个字节中,为了标识字符串结束。
在进行strlen(s)时,该函数由s的首地址开始查找,查找到00000000的结束符结束,返回长度为9是正确的。
r[9]就比较随机了,该语句代码划分一段长度为9的内存空间,并将此空间的首地址给r。但由于该内存中本来就存在以下值(假设):
00001100 00101010 00000000 ....
,所以在进行strlen(r)时,同样是由首地址开始找,找到第三个00000000结束符后结束,返回长度为2.打??代表不知道其具体值,但前两个??的值必然不是00。
由于内存中的值是不固定的,所以这个2必然也是随机的,这次可能为2,下次还可能为3,4,5,这个依赖于当前内存中数据的实际情况。
长度变成18原因,也是根据当前内存情况决定的。由于在运行程序的时候恰恰这样的分配的内存:
其中
\0
为字符串结束符,在内存中的值为00000000,转成16进制简写为00然后当执行你上面的程序后,最后变成了这样:
此时当我们在执行strlen(r)以及打印其值时,仍然是由r的起始位置开始,一直找到 00 结束符。这也就是你后面两个问题产生的原因。