繁体   English   中英

strlen(&string [])如何工作?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM