В выражении (i / 2) + func(&i)
компилятор (или реализация C в целом) может свободно вычислять либо i / 2
сначала, либо func(&i)
сначала. Точно так же в func(&j) + (j/2)
компилятор может сначала оценить func(&j)
или j/2
.
Приоритет не имеет значения. Приоритет говорит нам, как структурировано выражение, но не полностью определяет порядок, в котором оно оценивается. Приоритет говорит нам, что в a * b + c * d
структура должна быть (a * b) + (c * d)
. В a + b + c
приоритет в форме связи слева направо для +
говорит нам, что структура должна быть (a + b) + c
. Это не говорит о том, что a
должно быть оценено до c
. Например, в a() + b() + c()
структура имеет вид (a() + b()) + c()
, но компилятор может вызывать функции в любом порядке, сохраняя их результаты во временных регистрах, если это необходимо, и затем добавлять результаты.
В func(&j)+(j/2)
, нет приоритета справа налево или ассоциации. Ни одно из правил в стандарте C не гласит, что j/2
должно быть оценено до func(&j)
.
Компилятор может стремиться оценивать подвыражения слева направо, в отсутствие других ограничений. Однако различные факторы могут изменить это. Например, если одно подвыражение появляется несколько раз, компилятор может оценить его раньше и сохранить его значение для повторного использования. По сути, компилятор строит древовидную структуру, описывающую выражения, которые ему нужны для оценки, а затем ищет оптимальные способы их оценки. Это не обязательно происходит слева направо, и вы не можете полагаться на какой-либо конкретный порядок оценки.
Вопросы о секвенировании
Стандарт C содержит правило в C 2018 6.5 2 это говорит о том, что если модификация объекта, как происходит с i
в операторе *k+=4;
, не секвенирована относительно вычисления значения с использованием того же объекта, что происходит для i
в i / 2
, то поведение не определено. Тем не менее, эта проблема не возникает в этом коде, потому что модификация и вычисление значения являются неопределенно последовательными, а не последовательными: 6.5.2.2 10 говорит «… Каждая оценка в вызывающей функции (включая другие вызовы функций), которая иным образом специально не упорядочена перед или после выполнения тела вызываемой функции выполняется неопределенная последовательность действий относительно выполнения вызываемой функции ». C 5.1.2.3 3 гласит: «… оценки A и B имеют неопределенную последовательность , когда A последовательно или до, или после B, но не определено, какая…»