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

§5.1.2.4.16

实施例7表达式的分组不能完全确定其评估。 在以下片段中:

#include  int sum; char *p; /* ... */ sum = sum * 10 - '0' + (*p++ = getchar()); 

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

 sum = (((sum * 10) - '0') + ((*(p++)) = (getchar()))); 

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

所以基本上我把它理解为未指定的行为 – 要么*p = getchar(); p++; *p = getchar(); p++; 或者p++; *p = getchar() p++; *p = getchar() 。 注意; 意味着一个序列点,但整个表达式中没有其他序列点。

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

要么是*p = getchar(); p++; *p = getchar(); p++; 或者p++; p* = getchar() p++; p* = getchar() [sic]

确实没有。 它是:

 *p = getchar(); p++ 

要么

 old_p = p++; *old_p = getchar() 

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

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

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

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


从C11,6.5.2.4.2(强调我的):

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

词汇分组是无关紧要的。 重要的是p++价值

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

 sum = sum * 10 - '0' + (*p = getchar()); ++p; 
 sum = (((sum * 10) - '0') + ((*(p++)) = (getchar()))); 

相当于

 *p = getchar(); sum = ( ((sum * 10) - '0') + *p ); p++; 

它减少到1行。 并且它没有用处,因为以这种方式编写代码可以减少代码的大小和复杂性

 sum = (((sum * 10) - '0') + ((*(++p)) = (getchar()))); 

相当于

 p++; *p = getchar(); sum = ( ((sum * 10) - '0') + *p ); 

使用 – 和++进行指针赋值实际上并没有用。 考虑一个循环,您想要读取10个字符并在末尾添加转义字符:

 int i, sum; char * p; p = (char*) malloc(11 * sizeof(char)); for (i = 0; i < 10; i++){ sum = sum * 10 - '0' + (*p++ = getchar()); } *p = '\0';