Will "p = p + (* p) ++ * 3 + c;" cause undefined behavior?

Possible duplicate:
Undefined Behavior and Sequence Points

As defined in the standard, E1 + = E2 is almost the same for E1 = E1 + E2, except that E1 is evaluated only once. Thus, in addition, there will be "p + = (* p) ++ + c"; cause undefined behavior?

Try using the following code in gcc / g ++ (4.7 / 4.4). There are two kinds of results: bxxxxx (g ++ 4.7) or axbxxx (gcc, g ++ 4.4). If we execute (1), but not (2) in the code, we can only get axbxxx.

#include <stdio.h> int main() { char s[] = "axxxxx"; char *p = s; printf("s = %s in the beginning.\n" "p is pointed at the %d-th char.\n", s, p - s); //p = p + (*p)++ * 3 + 2 - 'a' * 3; // (1) p += (*p)++ * 3 + 2 - 'a' * 3; // (2) printf("p is moved ahead by %d steps\n", p - s); printf("s = %s after the operation.\n", s); return 0; } 

I cannot find why this causes undefined behavior, and I cannot claim that this is a gcc error.

For the result of axbxxx, I also can not understand why the operand or post ++ is evaluated twice (after receiving the value and then saving it). Since the standard says that "1 ... is added to it," I think that the address should be evaluated only once. If the address of the post ++ operand is evaluated only once, the effect of the expression will be the same, despite the fact that assignments are made in any order.

=== UPDATE ===

After reading the document linked in the first comment, I think the following rule matters:

"2) In addition, the previous value should be consulted only to determine the value to be stored.".

So, will access p in "p = p + (* p) ++ * 3 + c" be considered as part of the "previous value" * p, which has nothing to do with the value that needs to be stored in * p?

IMO, this rule is not violated.

+4
source share
4 answers

No, p = p + (*p)++ * 3 + c does not cause any undefined behavior, assuming p does not point to c .

In this case, the dubious part is reading and changing the *p value inside the expression. However, this value is read in order to determine the new p value (there is a direct dependence of the data of the new p value on the value read in *p ), therefore it does not violate the requirements.

I assume that the error in the compiler is actually due to incorrect behavior in an undefined situation. Note that the expression has two side effects: store the new value in p and save the new value in *p . It is not indicated in what order these side effects occur. However, during the evaluation of the (*p)++ subexpression, the compiler had to “fix” the specific lvalue argument for ++ to ensure that the new (incremented) value was stored in this exact object. It seems that the older version of the compiler could not do this, i.e. First, the new p value is evaluated, and then the new *p value is stored through the new p value. This is clearly wrong.

+3
source

In principle, the statement p += (*p)++ + c; potentially correct. All he does is move the pointer ( p ) to some value that is determined by the variable for which p points.

You just need to make sure that you never increase p outside s + 7 . I have not tested your code and shy, completely, to see if this case is not (but note that you are doing certain coding and shy tricks).

+1
source

Note that p += x; not equivalent to p = p + x; , but << 22>. x first evaluated, and the result is added to p. In a form without parentheses, as indicated in the header, an intermediate value for p can indicate outside the array, which is really undefined. The version in your code should be fine if the result for x is inside the array.

6.5.16.2.3 The composite assignment of the form E1 op = E2 differs from the simple expression E1 = E1 op (E2) only in that the lvalue E1 is evaluated only once.

J.2 undefined behavior - adding or subtracting a pointer in just behind it, an array object and an integer type that does not indicate an object or an object immediately behind it (6.5.6).

This definition of UB is not limited to the final result of the assignment.

+1
source

p += (*p)++ * 3 + 2 - 'a' * 3 not forms E1 = E1 + E2 .

  • On the right side you have a pointer (address variable)
  • On the left side, you are incrementing the variable addressed by this pointer.

EDIT: Spotted p+=

Still not undefined, because regardless of the evaluation order of each expression on the right-hand side of E1 = E1 + E2 value of p does not change.

0
source

Source: https://habr.com/ru/post/1438958/


All Articles