Порядок работы операторов C # - PullRequest
0 голосов
/ 21 ноября 2011

Я портирую утилиту C ++ на C #.Когда я запускаю следующий оператор в C ++, я получаю правильную операцию.Когда я выполняю ту же инструкцию в C #, однако ...

omgwtfbbq

Кто-нибудь знает, почему выполняется begin ++?Сумасшедшая вещь в том, что если я запускаю (i% 2) == 0 с i = 0, Немедленное окно возвращает true.

Ответы [ 3 ]

12 голосов
/ 21 ноября 2011

Приоритет оператора в этом вопросе не имеет значения. Это порядок оценки, который вызывает такое поведение.

В C # i++ оценивается до i % 2, поскольку он находится на левой стороне. Таким образом, i % 2 ложно, и вычисляется правая часть if.

Сначала вы используете приоритет для получения синтаксического дерева:

=
  buffer[i++]
  if i % 2
    then temp[end--]
    else temp[begin++]

На каждом узле вы оцениваете детей слева направо. Это означает, что i++ оценивается до i % 2.

Эрик Липперт имеет множество сообщений на эту тему, как здесь, на SO, так и в своем блоге:

Лично я бы избежал такого кода. Гораздо приятнее разбить его на несколько выражений или даже использовать простой оператор if вместо ? :


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

3 голосов
/ 21 ноября 2011

Не знаю, но почему бы вам просто не прояснить свои намерения?

if(i % 2 == 0) {
    buffer[i] = temp[end--];
} else {
    buffer[i] = temp[begin++];
}

i++;
0 голосов
/ 21 ноября 2011

Вы уверены, что begin < end правильно?В конце вы пропустите один элемент, если я не ошибаюсь.

Вот как я бы написал на C ++:

for (; begin <= end; ++i)
{
    buffer[i] = temp[(i & 1) == 0 ? end-- : begin++];
}

Но если подумать, то условноевнутри цикла действительно нет необходимости, потому что он переворачивается с каждой итерацией.Было бы более эффективно просто иметь две операции копирования внутри цикла:

while (begin < end)
{
    buffer[i++] = temp[end--];
    buffer[i++] = temp[begin++];
}
if (begin == end)
{
    buffer[i++] = temp[end--];
}

Я изменил условие цикла обратно на < и добавил if в случае нечетного числа элементов.

...