Термины "приоритет оператора" и "порядок оценки" очень часто используются в программировании и чрезвычайно важны для программиста. И, насколько я понимаю, эти две концепции тесно связаны; нельзя обойтись без другого, когда речь идет о выражениях.
Возьмем простой пример:
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. Является ли он Ошибка или нет?