无法理解 strcmp 函数的一小部分

Can't understand small part of strcmp function

我正在看一本 C 语言的书,看过这两个 strcmp 算法。

我已经了解了 for 循环的使用原理。

但这两个for循环对我来说是新的。我不明白这些部分

  1. for (i = 0; s[i] == t[i]; i++) 它没有长度而是有这个 s[i] == t[i].

  2. for ( ; *s == *t; s++, t++)这家伙是什么意思;.

我了解的其他部分,我也知道这些功能是什么returns。

   /* strcmp: return <0 if s<t, 0 if s==t, >0 if s>t */
int strcmp(char *s, char *t)
{
   int i;
   for (i = 0; s[i] == t[i]; i++)
       if (s[i] == '[=10=]')
     return 0;
   return s[i] - t[i];
}

int strcmp(char *s, char *t)
{
 for ( ; *s == *t; s++, t++)
  if (*s == '[=10=]')
  return 0;
 return *s - *t;
}

在第一种情况下,for 语句之后的代码正在检查是否找到了字符串结束标记,如果找到,函数 returns 0.

第二个for语句的情况下,for语句的初始化部分没有填写,所以语句以for( ;开头。这是完全合法的。

祝你好运。

For 循环有 3 个部分 - 初始化、条件和循环表达式。这些都是可选的。
所以这个循环-

for (i = 0; s[i] == t[i]; i++)

它一直运行到字符 s[i] 等于 t[i]。所以这是条件。如果它是假循环中断。

条件不一定总是基于长度。

还有这个 -

for ( ; *s == *t; s++, t++)  

正如我们在上面看到的那样,初始化 是可选的,这里不存在,这很好。此循环中的条件也相同 i.e 循环直到字符相等。

for (i = 0; s[i] == t[i]; i++) // It has no length

实际上这段代码有点危险,因为它假定传递的字符串以 NULL 结尾(但稍后阅读)。只有当字符串的左侧部分相等时,循环才会继续,因此在循环内部,当遇到 NULL 时,唯一可能返回的结果是 0(相等)(for(;;) 条件确保两个字符串在同一位置都有 NULL)。

关于长度,要计算它,您无论如何都应该扫描整个字符串……并且扫描两次(因为有两个字符串)。这个循环反而将所有结合在一起。此外,C 中的字符串必须 以 NULL 结尾。当然,没有其他方法可以进行这种比较!

for ( ; *s == *t; s++, t++) // what means this guys

这与前面的大致相同,但不是使用索引取消引用 s 和 t(并且不触及它们),而是将它们修改为指向字符,一个接一个。我相信这会更快,但取决于编译器。此外,递增 s 和 t 会使您丢失字符串的开头;但是在这个函数中是没有问题的。

关于for(;;)的语法,有评论已经解释了为什么要这样写。 for() 的最后一部分,在分号和右括号之间,在每次迭代后执行。在这种情况下我们需要增加两个变量,所以有两个语句用逗号分隔。

  1. 它没有长度。 for 循环是 运行 直到条件为真,所以在这种情况下,这意味着它将 运行ning 直到 s[i] 不等于 t[i]

  2. for ( ; *s == *t; s++, t++)

这里的

;表示省略了for循环的第一个子句。作为 bot st 是在 for 循环之外定义的,因此无需在此处定义它们。

C标准允许:

for ( clause-1 ; expression-2 ; expression-3 ) statement

(...)

Both clause-1 and expression-3 can be omitted. An omitted expression-2 is replaced by a nonzero constant.

某些编译器(例如 clang)在第一个子句中放入已定义的变量时会产生警告。例如这段代码:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
  int i = 0;
  for (i; i < 10; i++)
    puts("Hi");

  return EXIT_SUCCESS;
}

使用 clang 编译会产生警告:

main.c:7:8: warning: expression result unused [-Wunused-value]
  for (i; i < 10; i++)
       ^

首先,一些基础知识。

for 循环的语法是

for ( <em>expr1<sub>opt</sub></em> ; <em>expr2<sub>opt</sub></em> ; <em>expr3<sub>opt</sub></em> ) <em>statement</em>

expr1expr2expr3 中的每一个 是可选的。语句

for ( ; ; ) { // do something }

将循环 "forever",除非循环主体中某处有 breakreturn 语句。

expr1,如果存在,则在循环执行之前被计算一次——它用于建立一些初始状态(例如将索引设置为 0,或分配一个指针值,或类似的东西)。

expr2,如果存在,在循环体的每次迭代之前计算。它是继续循环执行的测试条件。如果表达式的计算结果为非零值,则执行循环体;否则,循环退出。如果缺少 expr2,则假定计算结果为 1 (true)。

expr3,如果存在,在循环体的每次迭代后计算。它通常会更新 expr2 中正在测试的任何内容。

for (i = 0; s[i] == t[i]; i++) It have no length instead have this s[i] == t[i]

只要s[i] == t[i]这个循环就会执行;一旦 t[i] 不等于 s[i],循环就会退出。就其本身而言,这意味着如果您有相同的字符串,循环将 运行 超过字符串的末尾 - 如果 st 都包含 "foo",则循环将运行 作为

s[0] == t[0] == 'f'
s[1] == t[1] == 'o'
s[2] == t[2] == 'o'
s[3] == t[3] == 0
s[4] == t[4] // danger, past the end of the string

因此,在循环体内,代码还会检查 a[i] 是否为 0 - 如果是,这意味着我们已经匹配了终止符 0 之前的所有内容,并且字符串是相同的.

所以,基本上,它是...

s[0] == t[0] == 'f', s[0] != 0, keep going
s[1] == t[1] == 'o', s[1] != 0, keep going
s[2] == t[2] == 'o', s[2] != 0, keep going
s[3] == t[3] == 0, s[3] == 0, at end of s, strings match

for ( ; *s == *t; s++, t++)

做的事情与第一个循环完全相同,但它没有使用 [] 运算符索引到 st,它只是使用指针。因为没有什么要初始化的,所以第一个表达式只是空的。