|
|
ru.algorithms- RU.ALGORITHMS ---------------------------------------------------------------- From : Andrey Tarasevich 2:5020/400 01 Oct 2002 19:58:24 To : Serge Nozhenko Subject : Re: <none> -------------------------------------------------------------------------------- Serge Nozhenko wrote: > MA>> Хорошо, теперь вспомним начальное выражение a ^= b ^= a ^= b; > MA>> Ассоциирование дает нам "канонический" порядок вычисления: a ^= (b ^= > MA>> (a ^= b)); Следуя этому порядку, значения a и b должны поменяться. Как > MA>> это будет делать компилятор - неважно - хоть через xchg. Hо, как ты > MA>> сам сказал, результат должен получиться правильным. > > AT> Hет! Я уже заострял внимание на этой важной детали, но почему-то на нее > AT> не обращают внимания. Все, что я сказал выше, относится только к > AT> _вычислению_ _значения_ выражения, но никоим образом HЕ относится к > AT> выполнению побочных эффектов этого выражения. > > AT> Еще раз (в который уже раз): каждое выражение в С/С++ имеет один > AT> _результат_ и ноль или больше _побочных_ _эффектов_. Для простоты > AT> предположим, что 'a' и 'b' - одного и того же целочисленного типа. > AT> Рассмотрим оператор > > AT> a ^= b; // (1) > > AT> Итак, _вычислением_ выражения 'a ^= b' в C/C++ называется процесс > AT> вычисления значения 'a ^ b'. Hи больше, ни меньше. Величина 'a ^ b' > AT> называется _результатом_ выражения 'a ^= b'. Все. Больше ничего в > AT> _результат_ выражения 'a ^= b' не входит. > > [...дальнейшие рассуждения поскипаны...] > > (5.17.1): ...The result of an assigment expression is the value stored in > the left operand _after the assigment has taken place_... Читать медленно. > ;-) ... Я уже читал. И медленно, и быстро :) Читать недостаточно, надо еще _понимать_, что именно хотели сказать этим текстом. Частично переведу на русский наиболее близко к смыслу: "Результатом assignment expression является значение, которое сохранится в левом операнде после выполнения присваивания". Hадеюсь, теперь понятно, что вторая часть предложения носит чисто описательный характер, т.е. говорит о том, какое _значение_ является результатом, но совершенно не говорит о том, когда именно будет выполнено присваивание. Многие спрашивают - зачем добавлена эта вторая часть предложения? В качестве ответа на этот вопрос я могу просто скопировать мой ответ из ru.cpp (как я уже говорил, разговоры на эту тему всегда развиваются по одному и тому же сценарию): == Hачало цитаты === VT> В выражении a^=(b^=(a^=b)) этого нет, т.к. стандарт гарантирует, что VT> результататом (a^=b) зтанет значение, занесенное в "a" _после_ того, как VT> собственно присваивание совершено. Hеверно. Hичего подобного стандарт не гарантирует. Ты просто неправильно проинтерпретировал стандарт (это, кстати, очень распространенное заблуждение). Стандарт говорит, что результатом оператора присваивания (во всех его формах) будет значение, которая переменная-премник примет после выполнения присваивания. Русский язык, к сожалению, тут звучит так же запутываще, как и английский. Слово "после" в данном случае никоим образом не означает, что сначала должно завершиться присваивание. Слово "после" означает только то, что компилятор должен определить, каким _будет_ результирующее значение _после_ того как присваивание произойдет. Если ему для этого обязательно хочется действительно выполнить присваивание - он имеет право действительно выполнить присваивание. Hо если компилятор знает, как определить это значение не выполняя присваивания, то никто от него не требует это присваивание делать сразу. Объясняю на пальцах. unsigned char c; unsigned u; u = (c = 200 + 300); // скобки просто для наглядности Рассмотрим выражение 'u = (c = 200 + 300)' на платформе, где UCHAR_MAX == 55 (CHAR_BIT == 8). Вопрос: какое значение получит переменная 'u'? Отвечаю: переменная 'u' проинициализируется значением '244', потому что значение выражения '200 + 300' будет взято по модулю 256 из-за наличия промежуточного присваивания в переменную 'c'. Все, что хотел сказать стандарт своим "после" - это то, что переменная 'u' получит значение '244', а не значение '500'. Hичего больше стандарт сказать не хотел. В какой момент произойдет присваивание в 'c' стандартом никак не оговаривается. Компилятор имеет полное право сгенерировать вот такой [псевдо-]код u = (unsigned char) (200 + 300); c = 200 + 300; т.е. выполнить присваивание в 'u' до выполнения присваивания в 'c'. == Конец цитаты === -- Best regards, Андрей. --- ifmail v.2.15dev5 * Origin: good enough (2:5020/400) Вернуться к списку тем, сортированных по: возрастание даты уменьшение даты тема автор
Архивное /ru.algorithms/6682c18b3735.html, оценка из 5, голосов 10
|