Yet another sequence point query: how does *p++ = getchar() work?

做~自己de王妃 提交于 2019-12-06 07:51:28

问题


§5.1.2.4.16

EXAMPLE 7 The grouping of an expression does not completely determine its evaluation. In the following fragment:

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

the expression statement is grouped as if it were written as

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

but the actual increment of p can occur at any time between the previous sequence point and the next sequence point (the ; ), and the call to getchar can occur at any point prior to the need of its returned value.

So basically I understand this as unspecified behavior - either *p = getchar(); p++; OR p++; *p = getchar(). Note that the ; implies a sequence point, but there are no other sequence points in the whole expression.

So this syntax is useless. And, pretty much, ++ and -- for pointer assignment is useless. Right?


回答1:


either *p = getchar(); p++; OR p++; p* = getchar() [sic]

Well actuall no. It's either:

*p = getchar(); p++

or

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

In your interpretation, you could either write at *p or *(p + 1) which is not true. In both interpretations, you write to where p originally pointed to, regardless of when the compiler decides to put the instruction that changes p. If it decides to put it before the write to *p, then it would have to make sure it keeps the old value to later write to (*old_p).

The suffix -- and ++ operators are actually quite nice shortcuts. Take this example:

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

This is a very concise implementation of strlen using suffix ++.


From C11, 6.5.2.4.2 (emphasis mine):

The result of the postfix ++ operator is the value of the operand. As a side effect, the value of the operand object is incremented (that is, the value 1 of the appropriate type is added to it). See the discussions of additive operators and compound assignment for information on constraints, types, and conversions and the effects of operations on pointers. The value computation of the result is sequenced before the side effect of updating the stored value of the operand. With respect to an indeterminately-sequenced function call, the operation of postfix ++ is a single evaluation. Postfix ++ on an object with atomic type is a read-modify-write operation with memory_order_seq_cst memory order semantics.




回答2:


The lexical grouping is irrelevant. What matters is the value of p++.

The statement is identical to the following two statements:

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



回答3:


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

is equivalent to

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

it was reduced to 1 line. and it's not useless because writing code in such way will allow to reduce the size and the complexity of your code

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

is equivalent to

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



回答4:


Using -- and ++ for pointer assignments isn´t actually useless. Consider a loop where you want to read 10 characters and add the escape character at the end:

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';


来源:https://stackoverflow.com/questions/16275813/yet-another-sequence-point-query-how-does-p-getchar-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!