Gcc weird behavior in some cases pre- / post-increment in an array (edited)

I am writing a compiler that matches, within the {} scope, by and large the semantics of C99. When trying to reverse-engineer how gcc handles certain undefined behavior, in particular chained before and after incrementing variables, I noticed that it is hopelessly confused if you combine this with changing assignments (for example, "* =",) and array access . Simplification to the simplest point of seeming complete confusion, gcc 4.6.3. evaluates (with and without the option -std = c99):

a[0] = 2;
a[0] *= a[0]++;

to

a[0] = 3.

Do I remember the standard wrong? Is any use of pre-or post-increment already undefined, and not just chained use in a compound expression?

Also, even if the "undefined" behavior above seems like a particularly bad way to calculate the result, since I could only see how you would justify the result 5 (= 2 * 2 + 1, then what I would do is post-increment after the assignment operator), or 6 (= 3 * 2, use the variable, and then immediately after increasing it and process it in parsing order - the parser almost certainly evaluates "* =" after evaluating the RHS expression). Any understanding of this is from the angle of C or C ++?

I noticed this when trying to combine arrays with integer bounds of expressions with preliminary and post-increment and implement it , it is really difficult ; but nonetheless, the above seems a bit like copying, given the flagship status of gcc.

This is under Ubuntu 12.04.

: , gcc , . , , , : (1) ; (2) ; (3) . , , " ".

: clang 6. clang, , , , .

+4
4

? - pre-or post-increment undefined, ?

( 2011 ):

6.5
...
2 , , . , , . 84)

84) ,
  i = ++i + 1;
  a[i++] = i;
  i = i + 1;
  a[i] = i;

Undefined undefined; ( , , ); . gcc - , , , - , .

, a[0] *= a[1]++ ( a[0], a[1] ).

, 3 , ...

  • r1 <- a[0] ( LHS)
  • r2 <- a[0] ( RHS)
  • r1 <- r1 * r2 ( )
  • a[0] <- r1 ( LHS)
  • a[0] <- r2 + 1 ( RHS)

; - , . gcc - , , ; undefined .

+3

( read-and-mutate, *=) - , . , a[0] *= a[0]++ . -, gcc .

, , :

x *= y++;

:

tmp1 = y + 1;        tmp2 = x * y;
x = tmp1;            y = tmp2;

.

, tmp, , . , , :

r1  = y;
r2  = r1 + 1;
r3  = x;
r4  = r3 * r1;
x = r4;
y = r2;

, , ? , ?

, , x y , gcc . , , , .

, , . . , , , . , r4 = r3 * r1; x = r4 r2 = r1 + 1; y = r2. , ?

+4

() a[0]++ : 3; a[0] 3. , ( ).

() a[0] *= <value> : /* old value of */ a[0] * <value>, a[0] a[0], <value>.

, () , . C , .

, ( ) - ( - ).
"Hello, World!". .

+2

It is called "undefined behavior". You change the same object twice a[0]in the same statement (without intermediate points in the sequence) once with the operator *=once with the operator ++. The behavior is undefined. Anything can happen, including a computer crash or worse.

Once the behavior is undefined, the arguments about what the compiler did are completely pointless. This is a mistake in your code. Fix it.

-1
source

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


All Articles