while(* s ++ = * t ++);在C.

时间:2014-07-03 05:21:04

标签: c

在K& R的C编程语言中,我继续看到像这样的代码 while(*s++ = *t++) ;这只是第5章指针的一个例子。这对我来说完全令人困惑,因为我虽然循环如下:

while (something is true)
    do what your assigned to do

C是某种特殊情况还是错过了什么?作为初学C程序员,这只是我的头脑。关于while(*s++ = *t++) ;如何运作的任何解释都会很棒。

我对(*s++ = *t++)表达式的含义并不感到困惑。我只是想知道为什么while循环体中没有任何东西。

7 个答案:

答案 0 :(得分:7)

如果打破了最简单的命令,你可以想到这样的代码:

while (1) {
    char c = *t;
    *s = c;
    s++;
    t++;
    if (!c) {
        break;
    }
}

要解释它的工作原理,请将*t指定给*s,然后评估结果(a=b计算得到的值)。如果它不为零,则继续。如果它为零,则结束循环。

答案 1 :(得分:4)

st最有可能是char *,这意味着它们会被终止。所以一旦你遍历它们,它们将返回0. 0在C

中是假的

答案 2 :(得分:3)

这里有几件事情发生了:

  • 赋值语句x = y实际上是表达式(等于刚分配的值),它本身可以用作更复杂表达式的一部分。这对于多个分配(x = y = z)以及while ((c = getchar()) != EOF)等循环条件非常有用。
  • 与Pascal或Java不同,C对布尔值并不严格。任何非零值都为真(即,导致执行ifwhilefor语句的正文)和零(无论0,{{1 }},0.0'\0')为false。
  • 字符串表示为由NUL(零)字符终止的字符数组(或指向此类数组的指针)。因此,如果NULL是指向字符串的指针,p表示它位于字符串的末尾。
  • postfix *p == 0运算符会递增其变量,但会返回旧值。
  • ++循环可能有一个空体。

总而言之,while是一个有效的C语句。

将增量移动到循环体中会给出等效语句:

while(*s++ = *t++);

将分配移动到循环体中会给出:

while (*s = *t)
{
   s++;
   t++;
}

或者,相当于

while (1)
{
   if (!(*s = *t))
   {
      break;
   }

   s++;
   t++;
}

原始表达式while (1) { // Copy one char from string t to string s. *s = *t; // If it was the string terminator, exit the loop. if (*s == '\0') { break; } // Move both pointers to the next character. s++; t++; } 只是上面代码高尔夫版本。

答案 3 :(得分:1)

在C中,每个字符串都以'\0'字符终止,其ASCII码为0

因此,当t中的所有字符串都被复制到s时。循环将终止,因为复制的最后一个字符为0,在C中为false

注意:在执行此类操作时,您应该注意Sequence Points

答案 4 :(得分:1)

表达式(*s++ = *t++)读取

  1. 阅读t
  2. 指出的字符
  3. 将该字符存储在s
  4. 指向的位置
  5. t指针提前1个位置
  6. s指针提前1个位置
  7. 返回复制的值(字符)
  8. 并且while();指令是

    • 虽然该值不为零(即我们尚未复制零字符串终止符)但不执行任何操作

    其中'什么都不做'是由最后单独的分号代表的空指令。

答案 5 :(得分:0)

来自C99 standerds

  An assignment expression has the value of the left operand after the assignment

t指向的值为NULL时。它将被分配到s指向的内存位置。并且该表达式的总值变为NULL。它将打破while循环。

答案 6 :(得分:0)

其他人已经回答了这个问题。虽然*s++ = *t++不幸是C中相当常见的一行,但我只想指出以下内容:

  • 在同一表达式中将++与其他运算符一起使用是危险的做法。总是有可能最终得到依赖于评估顺序的代码,这是一种未指明的行为。并且还有可能调用未定义的行为,以防你有意或无意地修改同一个变量两次而没有序列点。

    此外,正如我们从这个例子中看到的那样,将++与其他运算符结合使得代码不必要地难以阅读并强制程序员和阅读器100%确定C中的所有运算符优先级规则。

    最佳代码的编写方式使每个表达式只有一个副作用。因此,最佳代码不会将++与同一表达式中的其他操作数混合。 (参见MISRA-C:2004的规则12.2 12.4 12.13,关于++可能导致错误的一些例子。)

  • 在控制语句表达式中使用赋值被认为是不好的做法。它使代码更难阅读,并且有可能混合= ==。好的编译器警告不要使用= inside控制语句。 (见MISRA-C:2004 13.1)

所以你应该做的是将这些危险的,不可读的代码重写成更清晰,更安全的东西。例如:

*s = *t

while(*t != '\0')
{
  s++,
  t++;
  *s = *t;
}