首页 > 解决方案 > 在赋值中使用后缀/后缀运算符

问题描述

在赋值运算符的 lhs 上有一个后/前缀运算符是否可以接受?

#include<ctype.h>
void to_upper_in_place(char* string)
{
    while(*string++ = toupper(*string));
}

如果可以,之前的 C 代码是否被认为是可读的,还是应该变成类似下面的代码?

#include<ctype.h>
void to_upper_in_place(char* string)
{
    while(*string) {
        *string = toupper(*string);
        string++;
    }
}

甚至:

while(*string = toupper(*string++));

标签: c

解决方案


让我们看几个不同的案例。

(1)(使用两个不同的指针)

*dest++ = toupper(*src++);

这是完全普通的 C 风格。

(2)

*dest = toupper(*src);
src++;
dest++;

这是“长手”风格。如果您害怕++以危险的方式使用它,您可以编写它。(正如我们即将看到的那样,一定程度的谨慎确实是有道理的。)

(3)(回到lhs和rhs上的同一个指针)

*p = toupper(p);
p++;

这可以。

(4)

*p++ = toupper(*p);

这是有问题的,因为p在同一个表达式中同时使用和修改,而修改不取决于使用的值。在许多/大多数情况下,此模式呈现表达式undefined,这是一件坏事。最终很难说这种特殊情况是否实际上是未定义的,但出于这个原因,我们必须保持安全,并说 (3) 更可取。(有关这种未定义行为的更多信息,请参阅这个陷入困境的旧问题。)

(5)

*p = toupper(*p++);

这更糟。它同样可能是未定义的,但如果它确实有效,它可能会增加p得太快。

(6) 另一种安排是将增量放入循环头中,for而是使用循环:

for(; *p; p++)
    *p = toupper(*p);

这也很好。


推荐阅读