Термины "приоритет оператора" и "порядок оценки" очень часто используются в программировании и чрезвычайно важны для программиста. И, насколько я понимаю, эти две концепции тесно связаны; нельзя обойтись без другого, когда речь идет о выражениях.
Возьмем простой пример:
int a=1; // Line 1
a = a++ + ++a; // Line 2
printf("%d",a); // Line 3
Теперь видно, что Line 2
приводит к Undefined Поведению, так как Точки последовательности в C и С++ включают:
Между оценкой левого и правого операндов && (логическое И), || (логическое ИЛИ) и запятая операторы. Например, в выражение
*p++ != 0 && *q++ != 0
, все побочные эффекты подвыражения*p++ != 0
завершены перед любой попыткой доступа кq
.Между оценкой первого операнда троичного оператора "вопросительного знака" и второго или третьего операнда. Например, в выражении
a = (*p++) ? (*p++) : 0
имеется точка последовательности после первый*p++
, то есть он уже был увеличен к тому времени, когда выполняется второй экземпляр.В конце полного выражения. Эта категория включает выражение (например, присвоение
a=b;
), операторы возврата, контролируя выражения if, switch, while или do-while, и все три выражения в выражении for.Прежде чем функция будет введена в вызов функции. Порядок, в котором аргументы оцениваются не указанная, но эта точка последовательности означает, что все их побочные эффекты завершены до того, как функция вошел. В выражении
f(i++) + g(j++) + h(k++)
,f
вызывается с параметр исходного значенияi
, ноi
увеличивается до ввода телоf
. Аналогично,j
иk
являются обновлен перед входомg
иh
соответственно. Однако это не заданный в каком порядкеf()
,g()
,h()
выполняются и в каком порядкеi
,j
,k
увеличиваются. Значенияj
иk
в телеf
, следовательно, undefined. 3 Обратите внимание, что функция вызовf(a,b,c)
не используется запятой и порядка оценка дляa
,b
иc
равна не определено.При возврате функции, после того, как возвращаемое значение будет скопировано в вызывающий контекст. (Эта точка последовательности указан только в стандарте С++; он присутствует только неявно в С.)
В конце инициализатора; например, после оценки 5 в объявлении
int a = 5;
.
Таким образом, переходя по точке № 3:
В конце полного выражения. Эта категория включает в себя выражения (например, присваивание a = b;), операторы return, управляющие выражения if, switch, while или do-while и все три выражения в инструкции for.
Line 2
явно приводит к Undefined Поведению. Это показывает, как Undefined Поведение тесно связано с Точками последовательности.
Теперь возьмем еще один пример:
int x=10,y=1,z=2; // Line 4
int result = x<y<z; // Line 5
Теперь очевидно, что Line 5
сделает переменную result
сохранением 1
.
Теперь выражение x<y<z
в Line 5
может быть оценено как:
x<(y<z)
или (x<y)<z
. В первом случае значение result
будет 0
, а во втором случае result
будет 1
. Но мы знаем, когда вступает в игру Operator Precedence
Equal/Same
- Associativity
, следовательно, оценивается как (x<y)<z
.
Это то, что сказано в этой статье MSDN:
Приоритет и ассоциативность операторов C влияют на группировку и оценку операндов в выражениях. Приоритет оператора имеет смысл только в том случае, если присутствуют другие операторы с более высоким или более низким приоритетом. Сначала оцениваются выражения с операторами с более высоким приоритетом. Приоритет также можно описать словом "привязка". Говорят, что операторы с более высоким приоритетом имеют более жесткую привязку.
Теперь о статье:
Он упоминает: "Выражения с операторами с более высоким приоритетом оцениваются первыми".
Это может звучать некорректно. Но, я думаю, статья не говорит что-то неправильно, если мы считаем, что ()
также является оператором x<y<z
таким же, как (x<y)<z
. Мое рассуждение состоит в том, что ассоциативность не вступает в игру, тогда полная оценка выражений станет двусмысленной, поскольку <
не является Точка последовательности.
Кроме того, другая ссылка, которую я нашел, говорит об этом на Приоритет операторов и ассоциативность:
На этой странице перечислены операторы C в порядке приоритета (от наивысшего до самого низкого). Их ассоциативность указывает, в каком порядке применяются операторы с одинаковым приоритетом в выражении.
Итак, второй пример int result=x<y<z
, мы можем видеть здесь, что во всех трех выражениях есть x
, y
и z
, так как простейшая форма выражения состоит из одного литеральная константа или объект. Следовательно, результат выражений x
, y
, z
будет там rvalues , т.е. 10
, 1
и 2
соответственно. Следовательно, теперь мы можем интерпретировать x<y<z
как 10<1<2
.
Теперь, не вступает ли ассоциативность в игру, так как теперь у нас есть 2 выражения для оценки: 10<1
или 1<2
, и поскольку приоритет оператора тот же, они оцениваются слева направо?
Взяв последний пример в качестве аргумента:
int myval = ( printf("Operator\n"), printf("Precedence\n"), printf("vs\n"),
printf("Order of Evaluation\n") );
Теперь в приведенном выше примере, поскольку оператор comma
имеет одинаковый приоритет, выражения оцениваются left-to-right
, а возвращаемое значение последнего printf()
сохраняется в myval
.
В SO/IEC 9899: 201x в разделе J.1 Непоказанное поведение:
Порядок, в котором оцениваются подвыражения, и порядок, в котором побочные эффекты имеют место, кроме как указано для функции-вызова(), &, ||,?: и запятой операторов (6.5).
Теперь я хотел бы знать, было бы неправильно сказать:
Порядок оценки зависит от приоритета операторов, оставляя случаи Unspecified Behavior.
Я бы хотел, чтобы меня исправили, если были допущены какие-либо ошибки в чем-то, что я сказал в моем вопросе. Причина, по которой я опубликовал этот вопрос, связана с путаницей, созданной в моей голове статьей MSDN. Является ли он Ошибка или нет?