[英]How does strlen() calculate the length of a string not defined in the current function?
据我了解,在C数组和指向字符串的指针中没有隐式包含有关相应数组中元素数量的信息。 这就是为什么除了argv
之外,还必须将argc
传递给main()
。 但是,在我的机器上,即使未在与printf()
相同的作用域中定义字符串,以下代码也可以正确打印字符串"Hello"
的长度,即5
。
#include <stdio.h>
#include <string.h>
void p1(char *a)
{
printf("%lu\n", strlen(a));
}
void p2(char a[])
{
printf("%lu\n", strlen(a));
}
int main(int argc, char *argv[])
{
char *a = "Hello";
char b[] = "Hello";
char c[] = {'H', 'e', 'l', 'l', 'o', '\0'};
char d[] = {'H', 'e', 'l', 'l', 'o'};
p1(a);
p2(a);
printf("\n");
p1(b);
p2(b);
printf("\n");
p1(c);
p2(c);
printf("\n");
p1(d);
p2(d);
return 0;
}
这是我的结果和机器类型:
$ ./每年
5
55
55
56
6$ uname -a
Linux厌恶3.16.0-37-generic#51-Ubuntu SMP Tue May 5 5 13:45:59 UTC 2015 x86_64 x86_64 x86_64 GNU / Linux
和
$ cat / etc / issue
Ubuntu 14.10 \\ n \\ l
strlen()
如何确定字符串长度? 即使将字符串显式发送为指针(例如在函数调用函数p1(a)
为什么有效? 如果仅在较新版本的gcc
和clang
此行为,它何时开始运行,我可以在程序中依赖它吗?
编辑:
另外,当字符串中不包含空字节时,为什么strlen()
报告一个附加字符? (在编辑中添加)
编辑:我通过找到一个空字节解决了strlen()
工作的断言。
另外,当字符串中不包含空字节时,为什么strlen()报告一个附加字符? (在编辑中添加)
明确回答您的修改:您的假设是错误的。 它可能返回42
,崩溃甚至删除您的文件。 阅读有关未定义行为的信息,如先前的评论所建议。
报告6的技术原因是偶然的,在您的最终程序中,数组后面有2字节的0字节。 但这不能使数组成为有效的C字符串。
首先,您的函数p1
和p2
完全相同。 并非不是其中一个将字符串视为指针,而另一个将字符串视为数组。 根据定义,字符串是字符数组。 但是 ,每当我们操作数组时(尤其是将数组传递给函数时),我们实际使用的是指向数组第一个元素的指针。 因此,即使您的函数p2
看起来正在接收数组,它实际上仍在接收指针。 另请参阅C常见问题解答列表中的此问题 。
现在,第二,C字符串确实包含其长度的指示:所有适当的字符串都包含一个空终止符,即特殊字符'\\0'
,用于标记其结尾。 确定字符串长度的方法是通读它,对字符进行计数,直到找到'\\0'
为止。 这正是strlen
所做的。
最后,我们来到您的数组d
。 如我所知,您已经安排好该数组看起来像字符串"Hello"
,但没有终止的空字符。 因此,当strlen
尝试计算d
的长度时,它将一直超出末尾,并开始检查数组末尾是否存在任何随机的内存区域。 可能会发生三件事:
strlen
恰好会计算出正确的答案5。 strrlen
计算出的答案可能大于5,甚至可能大于5。这就是事实。 strlen
可能会运行到分配给您的进程的内存末尾,在这种情况下,您会收到一些操作系统级别的错误消息,例如分段冲突或总线错误,或者“此程序意外终止”或“死亡蓝屏”。 strlen
的实现
size_t strlen(const char * str) {
const char * s;
for (s = str; *s; ++s);
return(s - str);
}
循环终止条件*s
在内部为*s != '\\0'
。 因此,它一直循环直到找到终止null
字符。 并且, pointer to char
和char array
pointer to char
行为相同。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.