2016-07-17 5 views
3

Я хочу обменять значения указывает int *x и int *y используя выражениеразница между C и C++ относительно «=» оператор

*x ^= *y ^= *x ^= *y; 

(Ну, я знаю, что это выражение неудобно, и Я просто хочу знать разницу, без обид.) Это работало в C++, но не в С. Однако если разделить его на три части, как показано ниже

*x ^= *y; 
*y ^= *x; 
*x ^= *y; 

Он отлично работает на обоих языках.

Какая разница между оператором ^= в C и C++?

+6

** - 1 ** Я прекратил читать при «* x^= * y^= * x^= * y;". Если вы собираетесь задать вопрос, введите код, который менее отталкивает. Благодарю. –

+2

@ Cheersandhth.-Alf Я боюсь, что эта отталкивающая линия - вот что вопрос в конце. –

+2

Не знаете, почему downvotes? Вопрос содержит рабочий код, который воспроизводит ошибку.Это не так много вопросов. Он также представляет интересную разницу между 'C' и' C++', которые могут укусить других людей. Неужели мы действительно проголосовали за кодовое снобизм? – Galik

ответ

10

Разница не в указателях, как вы подозревали вначале, но в другом порядке правил оценки. В «новой» 11 C++ «Sequenced-до того правила», мы имеем:

Побочный эффект (модификация левого аргумента) оператора присваивания встроенной и всех встроенных сложные вычисления присваиваются после вычисления значения (но не побочных эффектов) как левого, так и правого аргументов и секвенируются перед вычислением значения выражения присваивания (то есть перед возвратом ссылки на модифицированный объект)

(От cppr.) Это правило гарантирует желаемую оценку вашего выражения налево-вправо.

В отличие от этого, C и C++ 98 используют «Точки последовательности». Так как в длинном заявлении нет точек последовательности, у вас есть несколько неощутимых изменений значений, на которые указывают указатели, и, таким образом, вызывать Undefined Behavior.

Для C gcc предупреждает об этом (live). Для C++ 98 он, по-видимому, уже использует новые правила, что прекрасно, потому что неопределенное поведение не определено.

Разделение утверждения решает эту проблему, конечно, потому что конец инструкции явно вводит точки последовательности, в которых они вам нужны. Это также превосходно, потому что оно более читаемо и не нужно знать правила последовательности, чтобы определить, правильно ли код.


Для справки: Большое разъяснение правил секвенирования в C++ можно найти here.

+0

Хорошо заметили, +1. Но обратите внимание, что это отвечает только на текущий вопрос, а не на оригинальный вопрос о указателях. –

+0

@ Cheersandhth.-Alf Сделал это явным, thx. –

+0

Было бы лучше, если бы вы могли предоставить более подробные аннотации к стандарту _Sequence points_ и _side effect_, поэтому для начинающих, как я, может быть полезно прочитать об этом больше. Вот связанная статья: [Неопределенное поведение и точки последовательности] (http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points) –

2

Чтобы ответить на поставленный вопрос: нет разницы между исходными указателями между C и C++.

Но я думаю, что ваш вопрос в том, что-то еще ...

+1

Упрощенный, потому что это единственный ответ, который обращается к исходному вопросу *. –

+0

Ваше предположение было правильным: сначала я подумал, что это проблема указателя, после того, как я прочитал ответы, я обнаружил, что это скорее связано с порядком оценки_, или что-то, что называется _sequence point_ и _side effect_, о котором я мало знал. –

3

Это неопределенное поведение, чтобы изменить ту же переменную более одного раза в одном операторе, так что компилятор имеет право делать что-либо, когда вы делаете *x ^= *y ^= *x ^= *y. Это по той же причине, почему ++i + i++ или тому подобное всегда неправильно.

+1

Боковое примечание '++ i + i ++ или тому подобное всегда неверно' является фиктивным. Это UB согласно стандарту – sjsam

+2

Я имел в виду, что это никогда не то, что вы намеревались сделать. Однако я вижу, как я был неверно истолкован. –

+1

Код не UB в C++ 11 и более поздних версиях. –

Смежные вопросы