又一个序列点查询:* 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';