Каков порядок оценки в C # и C ++? - PullRequest
5 голосов
/ 27 ноября 2010

Я пробовал следующую вещь в C # и C ++:

int a = 5;
int b = (a++)+(++a)+(a--)+(--a);

Я пытался получить результат b в C # и C ++.Но я получил разные ответы на оба вопроса.

Я получил 23 на C # и 20 на C ++.

Итак, пожалуйста, ответьте мне, почему это так?Какие могут быть причины для этого?

Ответы [ 4 ]

7 голосов
/ 27 ноября 2010

C # оценивает это слева направо.В C ++ смешные выражения , такие как ваше, вызывают неопределенное поведение , потому что вы изменяете переменную и читаете ее снова без промежуточной точки последовательности .

Это означает, что разные компиляторы (или даже один и тот же компилятор с разными настройками оптимизации) могут (и обычно будет ) выдавать разные результаты для (a++)+(++a)+(a--)+(--a).

4 голосов
/ 27 ноября 2010

Выражение имеет четко определенное поведение в C # (оценка слева направо)

В C # вывод будет 24 (не 23)

int b = (a++)+(++a)+(a--)+(--a);

      // 5   +   7 + 7   +   5 = 24

В C ++ выражение вызывает Неопределенное поведение , поскольку a изменяется более одного раза между двумя точками последовательности .

0 голосов
/ 18 мая 2017

Нужно все равно это искать, так что подумал, что я тоже опубликую это здесь.

Из спецификации C # 5.0

5.3.3.21 Общие правила для выражений со встроеннымивыражения

К этим видам выражений применяются следующие правила: выражения в скобках (§7.6.3), выражения доступа к элементу (§7.6.6), выражения базового доступа с индексацией (§7.6.8), выражения приращения и уменьшения (§7.6.9, §7.7.5), выражения приведения (§7.7.6), унарные выражения +, -, ~, *, двоичные символы +, -, *, /,%, <<,>>, <, <=,>,> =, ==,! =, is, as, &, |, ^ выражения (§7.8, §7.9, §7.10, §7.11), составные выражения присваивания (§7.17.2) проверенные и непроверенные выражения (§7.6.12), а также выражения для создания массивов и делегатов (§7.6.10).

Каждое из этих выражений имеет одно или несколько подвыражений, которые безусловно являются оценивается в фиксированном порядке (выделено мое) .Например, бинарный оператор% оценивает левую часть оператора, а затем правую.Операция индексирования оценивает индексированное выражение, а затем оценивает каждое из индексных выражений в порядке слева направо.

Подробные правила для каждого вида выражений приведены в разделе 7. Я не буду перечислять их все здесь, но эвристика слева направо, как написано в коде.Например,

7.5.1.2 Оценка списков аргументов во время выполнения

Выражения списка аргументов всегда вычисляются в том порядке, в котором они написаны.Таким образом, пример

class Test
{
     static void F(int x, int y = -1, int z = -2) {
          System.Console.WriteLine("x = {0}, y = {1}, z = {2}", x, y, z);
     }
     static void Main() {
          int i = 0;
          F(i++, i++, i++);
          F(z: i++, x: i++);
     }
}

производит вывод

x = 0, y = 1, z = 2
x = 4, y = -1, z = 3
0 голосов
/ 27 ноября 2010

Посмотрите здесь для полного списка C ++.Как говорит FredOverflow, C # оценивается слева направо

...