[英]How does strlen(&string[]) work?
这可能是一个很长的问题。 我正在用C测试一些字符数组,因此出现了这段代码。
char t[10];
strcpy(t, "abcd");
printf("%d\n", strlen(&t[5]));
printf("Length: %d\n", strlen(t));
现在显然strlen(&t[5])
产生3,而strlen(t)
返回4。
我知道字符串长度为4,这从插入四个字符很明显。 但是为什么strlen(&t[5])
返回3?
我的猜测是
String: a | b | c | d | 0 | 0 | 0 | 0 | 0 | \0
Position: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
strlen(&t[5])
查看由位置6、7和8组成的字符串的长度(因为第10个字符是NULL终止符,对)?
好的,然后我做了一些实验,并修改了一些代码。
char t[10];
strcpy(t, "abcdefghij");
printf("%d\n", strlen(&t[5]));
printf("Length: %d\n", strlen(t));
现在,这一次strlen(&t[5])
产生5,而strlen(t)
为10,正如预期的那样。 如果我正确理解字符数组,则状态现在应该为
String: a | b | c | d | e | f | g | h | i | j | '\0'
Position: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10
那么为什么strlen(&t[5])
这次返回5? 我已经声明了一个长度为10的字符数组,那么按照上面应用的相同逻辑,结果应该是4吗?
另外,由于NULL终止字符实际上位于第11位,我是否也应该遇到一些编译器错误? 我是C语言的新手,非常感谢任何人的帮助。
首先让我告诉你,你的“假设”
String: a | b | c | d | 0 | 0 | 0 | 0 | 0 | \0
Position: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
是不正确的。 根据您的代码,仅在“索引4 ”之前“保证”值,而不会超出该值。
对于第一种情况 ,在您的代码中
printf("%d\n", strlen(&t[5]));
由于各种原因而错,
%zu
用作size_t
类型。 &t[5]
没有指向有效的字符串 。 上面的任何一个(或两个)都会导致未定义的行为,并且任何输出都无法证明其合理性。
详尽地定义
char t[10];
strcpy(t, "abcd");
您为t
填充了索引0到3,索引4保留了空终止符。 从t[5]
开始的内容是不确定的。
因此, &t[5]
不是指向字符串第一个元素的指针,因此不能用作strlen()
参数。
确实,两者都有可能,也有可能。 UB是UB,没有理由。
然后,对于第二种情况,您说
char t[10];
strcpy(t, "abcdefghij");
再次访问内存超出范围。
您总共有10个数组元素来存储一个字符串,因此您可以有9个其他char
元素以及一个null终止符(将char数组限定为字符串)。
但是,您尝试放入10个char
元素,再加上一个空字符(在strcpy()
),因此您被一一弃用,访问绑定内存不足,调用UB。
char t[10];
未初始化,因此仅包含垃圾值1) 。 strcpy(t, "abcd");
用字符串“ abcd”和空终止符覆盖前5个字符。
但是, &t[5]
指向空终止后的第一个字符,这仍然是垃圾。 如果从那里调用strlen
,则任何事情都可能发生,因为传递的指针不太可能指向以null结尾的字符串。
1)垃圾=不确定值。 假设一个理智的2的补码系统,将使用缓冲区t
的地址,因此直到strlen
开始读取数组t
的边界之外的代码才调用未定义的行为。 参考 。
问题一:
我的猜测是
String: a | b | c | d | 0 | 0 | 0 | 0 | 0 | \\0 Position: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
这个假设是错误的。 数组未初始化为容纳0个值,但包含一些“随机”垃圾。 复制"abcd"
后,数组的上半部分( t[5]
等)仍然未触及,由于行为不确定,导致字符串的“随机”长度。
问题2:
如果我正确理解字符数组,则状态现在应该为
String: a | b | c | d | e | f | g | h | i | j | '\\0' Position: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10
再次错误。 您的数组仅包含10个字符。 它们位于索引0..9。 索引10超出范围。 您的复制操作可能会导致这种布局,或者也可能会在超出范围时崩溃。
但这不是由编译器检查的。 如果您遇到问题,那么它将在运行时。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.