Компилятор может изменить порядок выполнения операторов, когда он считает это целесообразным для целей оптимизации, и когда такие изменения не изменят наблюдаемое поведение кода.
Очень простой пример -
int func (int value)
{
int result = value*2;
if (value > 10)
{
return result;
}
else
{
return 0;
}
}
Наивный компилятор может сгенерировать для этого код в точности в указанной последовательности. Сначала вычислите «результат» и верните его только в том случае, если исходное значение больше 10 (если это не так, «результат» будет проигнорирован - вычисляется без необходимости).
Однако здравомыслящий компилятор увидит, что вычисление «результата» необходимо только тогда, когда «значение» больше 10, поэтому может легко переместить вычисление «значение * 2» в первые фигурные скобки и делать это только в том случае, «value» на самом деле больше 10 (не говоря уже о том, что компилятор не действительно смотрит на код C при оптимизации - он работает на более низких уровнях).
Это всего лишь простой пример. Гораздо более сложные примеры могут быть созданы. Вполне возможно, что функция C в конечном итоге будет выглядеть совсем не так, как ее представление C в скомпилированной форме, с достаточно агрессивной оптимизацией.