As a general rule, the compiler is allowed to do anything at all as long as the outcome is the same as if it had compiled your code exactly as written.
In fact, your typical C/C++ compiler, with any reasonable optimization flags enabled, given a function like:
void f (void) {
int a = 20;
int b = 10;
}
will simply compile it as:
f:
ret
In other words, it will treat it as an empty function. The reason is that the function has no effects whatsoever; those variables are assigned to, but their values are never used (in technical terms, they are dead stores), and thus the compiler can ignore them.
Now, let's look at a more practical example:
void foo (int num, int * num2, int * num3) {
*num2 = num * 2;
*num3 = num * 3;
}
Can the compiler reorder those statements? The answer is a firm no. The reason is that num2
and num3
may point to the same address (in other words, you may call the function like foo(3, &bar, &bar)
), and thus the order of the writes matters. On the other hand, in C only (but not C++), we could write it like so:
void foo (int num, int * restrict num2, int * restrict num3) {
*num2 = num * 2;
*num3 = num * 3;
}
In that case, the restrict
keyword tells the compiler that the pointers must point to different addresses, and thus reordering the statements is allowed, as the results are the same regardless of the order in which they are executed.