Home > Blockchain >  How to understand sequenced-before and reorder?
How to understand sequenced-before and reorder?

Time:01-08

Sequenced-before is defined in C standard that

If A is sequenced before B, then evaluation of A will be complete before evaluation of B begins

And there is a long list of rules about when A is sequenced-before B.

However, from this list I find a full expression is sequenced before the next full expression. Since an entire expression statement is a full expression, so in the following codes, 3/4/5 are full expressions while 1/2 are not(they are declaration statements).

int main(){
    int a = 1; // 1
    int b = 2; // 2
    a = 10; // 3 
    b = 20; // 4
    printf("%d %d", a, b); // 5
}

So, according to definition of sequenced-before, can compiler/CPU reorder 3/4?

I have two answers:

  1. No, they can't

    This is because 3 is sequenced-before 4, so 3 must be executed before 4.

  2. Yes, the can

    According to the as-if rule, C allows any and all code transformations that do not change the observable behavior of the program. Since the order of 3 and 4 does not matter, so compiler/CPU have every reason to reorder, according to as-if rule.

Seems I get a contradiction here.

UPDATE

How about

int main(){
    int a = 1; // 1
    int b = 2; // 2
    a = random_int(); // 3 
    b = random_int(); // 4
    printf("%d %d", a, b); // 5
}

CodePudding user response:

A compiler may only re-order 3 and 4 if you can't observe that reordering.

Here's an example of one (arguably) doing so

The resulting object code enregisters the 20 before the 10

.LC0:
        .string "%d %d"
main:
        sub     rsp, 8
        mov     edx, 20
        mov     esi, 10
        xor     eax, eax
        mov     edi, OFFSET FLAT:.LC0
        call    printf
        xor     eax, eax
        add     rsp, 8
        ret

An alternative explanation is that this isn't a reordering, those expression are gone. Notice how there's no mention of 1 or 2 anymore.

CodePudding user response:

You don't need to worry about reordering, at least as long as your program is single-threaded.

The seqenced-before relation determines what behavior you're going to see.

The compiler can then reorder whatever it wants, as long as observable behavior conforms to sequenced-before.


How about random_int()?

It doesn't matter what functions you call, reordering isn't going to affect the observable behavior.


Since an entire expression statement is a full expression, so in the following codes, 3/4/5 are full expressions while 1/2 are not(they are declaration statements).

If we're splitting hairs, none of them are full-expressions. :P

In

int a = 1; // 1
int b = 2; // 2
a = 10; // 3 
b = 20; // 4
printf("%d %d", a, b); // 5

Full-expressions are: 1, 2 (the initializers), a = 10, b = 20, printf("%d %d", a, b).

a = 10; (with ;) is an expression-statement, but not an expression. If you remove the ;, it turns into a full-expression.

  •  Tags:  
  • Related