又一个序列点查询:*p ++ = getchar()如何工作?

Vor*_*rac 3 c sequence-points

§5.1.2.4.16

实施例7表达的分组并不完全决定其评估.在以下片段中:

#include <stdio.h>
int sum;
char *p;
/*
...
*/
sum = sum * 10 - '0' + (*p++ = getchar());
Run Code Online (Sandbox Code Playgroud)

表达式语句被分组,就好像它被写为

sum = (((sum * 10) - '0') + ((*(p++)) = (getchar())));
Run Code Online (Sandbox Code Playgroud)

但是p的实际增量可以在前一个序列点和下一个序列点(;)之间的任何时间发生,并且对getchar的调用可以在需要其返回值之前的任何点发生.

所以基本上我把它理解为未指明的行为 - 要么是*p = getchar(); p++;OR p++; *p = getchar().请注意,这;意味着一个序列点,但整个表达式中没有其他序列点.

所以这种语法没用.而且,几乎,++和 - 用于指针分配是没用的.对?

Ker*_* SB 6

词汇分组是无关紧要的.要紧的是p++.

该陈述与以下两个陈述相同:

sum = sum * 10 - '0' + (*p = getchar());
++p;
Run Code Online (Sandbox Code Playgroud)


Sha*_*baz 6

或者*p = getchar(); p++;OR p++; p* = getchar() [原文如此]

好吧,没有.它是:

*p = getchar(); p++
Run Code Online (Sandbox Code Playgroud)

要么

old_p = p++; *old_p = getchar()
Run Code Online (Sandbox Code Playgroud)

在你的解释中,你可以写*p*(p + 1)不是真的.在这两种解释p中,无论编译器何时决定放置更改的指令,都要写入最初指向的位置p.如果它决定将它放在write to之前*p,则必须确保它保留旧值以便稍后写入(*old_p).

后缀--++运算符实际上是非常好的快捷方式.举个例子:

size_t strlen(const char *str)
{
    size_t len = 0;
    while (str[len++]);
    return len - 1;
}
Run Code Online (Sandbox Code Playgroud)

这是strlen使用后缀的非常简洁的实现++.


从C11,6.5.2.4.2(强调我的):

postfix ++运算符的结果是操作数的值.作为副作用,操作数对象的值递增(即,将相应类型的值1添加到其中).有关约束,类型和转换以及操作对指针的影响的信息,请参阅加法运算符和复合赋值的讨论.在更新操作数的存储值的副作用之前,对结果的值计算进行排序.对于不确定顺序的函数调用,后缀++的操作是单个评估.具有原子类型的对象上的Postfix ++是具有memory_order_seq_cst内存顺序语义的读取 - 修改 - 写入操作.

  • "听起来有一些规则,即后缀运算符在表达式完成后生效" - 不,它没有.为什么不尝试阅读和理解你给出的答案?或者就此而言,阅读C标准,它明确而明确地将`*p ++`中的'p`的值定义为增量前的值,*无论何时增加*.不要嘲笑史蒂夫的有效评论. (2认同)