#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char qq[] = {'a' , 'b' , 'c' , 'd'};
char qqq[] = "abcd";
printf("%d\n" , sizeof qq / sizeof qq[0]); // line A
printf("%d\n" , strlen(qq)); // line B
printf("%d\n" , sizeof qqq / sizeof qqq[0]); // line C
printf("%d\n" , strlen(qqq)); // line D
system("pause");
return 0;
}
查看上面的代码。数组qq
中有四个元素,数组qqq
中有五个元素,其中最后一个是'\0'
。所以我理解A行打印4
,C行打印5
。 D线对我来说还可以。我知道在处理字符串时strlen(qqq)
等于"sizeof qqq / sizeof qqq[0] - 1"
。但是B行打印15
让我感到困惑。为什么? (我使用vs2012。)
答案 0 :(得分:8)
在您的代码中
char qq[] = {'a' , 'b' , 'c' , 'd'};
qq
没有资格被称为字符串,因为它不是以空值终止的。因此,调用strlen()
wilh qq
会引发麻烦。
这里实际发生的是,strlen()
越过qq
中的最后一个有效元素来寻找终止null(实际上是缺失的),因此冒险进入越界内存,它会调用undefined behaviour。
解决方案:要使qq
成为字符串,您必须自己在初始化列表中添加null-terminator,例如
char qq[] = {'a' , 'b' , 'c' , 'd', '\0'};
就是说,正如我在评论中已经提到的那样,strlen()
返回类型为size_t
,您应该使用%zu
格式说明符来打印结果。
心情较轻,回答
strlen()在此代码中应该返回什么内容?
如果我说,&#34;尊敬的印度总统的电话号码&#34; ,从技术上讲,我可能正确!!
严肃地说,UB的输出是,未定义。
答案 1 :(得分:4)
您的字符串不是以空值终止的。这意味着您的代码不具有确定性。只要遇到strlen()
(空字节/字符),\0
就会终止;结果可能因顺序扫描而有所不同,直到遇到\0
。
答案 2 :(得分:3)
strlen()
计算字符串的长度,但char qq[] = {'a' , 'b' , 'c' , 'd'};
不是字符串。将'Non-String'
数据传递给strlen
时,会获得未定义的结果。
null terminated
中的字符串c
。
应为char qq[] = {'a' , 'b' , 'c' , 'd','\0'};
答案 3 :(得分:2)
strlen
将继续前进,直到找到\0
字符,计算沿途有多少个字符。
由于qq
中没有\0
,strlen
继续 进入其他不相关的内存。最终偶然会遇到\0
字节。
显然是在15个字节之后(或超出qq
结尾的11个字节)
但它不具有确定性或保证,并且非常不安全。很可能strlen
最终会在找到{{}之前尝试读取无效内存。 1}}字符,在这种情况下,你的程序会出现seg-fault。