如果 c == '\0',函数 Strrchr 如何找到最后一个 c?

How does the function Strrchr finds the last c if c == '\0'?

例如 char *p 指向 "there is so [=11=]ma[=11=]ny [=11=] \0 in t[=11=]his stri[=11=]ng ![=11=][=11=][=11=][=11=]" 中的第一个字符, Strrchr() 如何找到最后一次出现的空字符?

出现以下问题:
=>停止循环需要什么条件!
=>我认为在所有情况下它都会尝试访问下一个内存区域以检查其条件?在某些时候绕过字符串边界,UB!所以安全吗!

如有错误欢迎指正!

在您提供的情况下,您永远无法知道找到的空字符是否是最后一个字符,因为您无法保证字符串的结尾。因为它是一个 c 字符串,所以可以保证字符串以 '\0' 结尾,但如果您决定超越它,您将无法知道您正在访问的内存是否是您的。从数组中访问内存具有未定义的行为,因为您可以只访问内存中属于您的下一个对象,或者您可以触摸未分配的内存,但它的块仍然属于您的进程,或者您可以尝试触摸一个根本不属于您的细分市场。只有第三个会导致 SIGSEGV。您可以看到 问题来检查分段错误而不会使您的程序崩溃,但是您的字符串可能在您以这种方式捕获它之前就已经结束了。

字符串有一个结束字符是有原因的。如果您坚持在字符串的多个位置使用 \0,您可以用另一个字符终止,但请注意,所有库函数仍会将第一个 \0 视为字符串的结尾。

在字符串中使用多个 \0 被认为是一种不好的做法,也是一件非常糟糕的事情,所以如果可以的话,请避免使用它。

很简单,如评论中所述。 first [=16=] 是 C 字符串中的最后一个也是唯一一个。

所以如果你写

char *str = "there is so [=10=]ma[=10=]ny [=10=] \0 in t[=10=]his stri[=10=]ng ![=10=][=10=][=10=][=10=]";
char *p = strrchr(str, 's');
printf("%s\n", p);

它将打印

so 

因为strchr会在“so”中找到's',也就是你给它的字符串中的最后一个's'。并且(回答你的具体问题)如果你写

p = strrchr(str, '[=12=]');
printf("%d %s\n", (int)(p - str), p+1);

它将打印

12 ma

证明 strchr 找到了 第一个 [=16=].

很明显,str 是一个长字符串,其中嵌入了一些 [=16=]。但是,在 C 语言中, 没有 这样的东西作为“其中嵌入了 [=16=] 的字符串”。根据定义,C 字符串不可能包含嵌入的 [=16=]。根据定义,第一个 [=16=] 结束字符串。


还有一点。您曾提到,如果您要“访问下一个内存区域”,您将“在某个时候绕过字符串边界,UB!”你是对的。在我的回答中,当我说

p = strrchr(str, '[=12=]');
printf("%d %s\n", (int)(p - str), p+1);

这里,p 指向 strrchr 认为是字符串的结尾,所以当我计算 p+1 并尝试使用 %s 打印它时,如果我们不知道更好,看起来我确实误入了未定义的行为。在这种情况下,当然是安全的,因为我们确切地知道第一个 [=16=] 之外的内容。但是如果我写

char *str2 = "hello";
p = strrchr(str2, '[=15=]');
printf("%s\n", p+1);         /* WRONG */

那我肯定过关了

“一个字符串”、“一个字符数组”和“一个 char* 指针”是有区别的。

  • C 字符串是由空字符终止的字符数。
  • 字符数组是定义的字符数。
  • char* 指针在技术上是指向单个字符的指针,但通常用于标记 C 风格字符串中的一个点。

你说你有一个指向字符(char*p)的指针并且*p的值是't',但是你认为*p是一个C的第一个字符样式字符串 "there is so [=13=]ma[=13=]ny [=13=] \0 in t[=13=]his stri[=13=]ng ![=13=][=13=][=13=][=13=]".

正如其他人所说,因为你说这是一个 C 风格的字符串并且你不知道它的长度那么 p 之后的第一个 null 将标记字符串的结尾。

如果这是一个字符数组 char str[40] 那么您可以通过从数组末尾向开头循环来找到最后一个 null for (i=39; i>=0; i--) 但是您不知道长度,因此不行。

希望对您有所帮助,如果我误入了 C++,请原谅,我使用 C 已有 25 年了:)