c - 在赋值中使用后缀/后缀运算符
问题描述
在赋值运算符的 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++));
解决方案
让我们看几个不同的案例。
(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);
这也很好。
推荐阅读
- c++ - 处理 std::reference_wrapper 的最佳方法
作为 std::reference_wrapper - jenkins - 仅在手动启动构建时如何运行阶段
- vuejs2 - 可快速编辑的配置文件,公众访问者看不到?
- c# - x:绑定和用户控件
- automation - 自动热键 - 选项卡触发后热字串不起作用
- python - 这个 ImportError 来自哪里?
- amazon-web-services - AWS 的无服务器框架:将初始数据添加到 Dynamodb 表中
- python - 如何在 vue flask 应用程序中获取 Windows 用户名?
- php - 如何以这种 hh:mm - hh:mm 的格式计算经过的小时数?
- r - 关闭“重复标题”选项的表