Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.145.59.165] |
|
Сообщ.
#1
,
|
|
|
есть код { int x = 0; x = x++; } бред, конечно. Но возникает вопрос: чему должен быть равен x? По идее - 0, в самом деле имеем: выполняется x++, и возвращает значение x до инкремента, а потом выполняется оператор =, присваивающий результат x++ переменной x. Понятно, что результат x++, даст 0. Но, о чудо! x == 1! Как такое может быть???
Испробовал VC++ 7.0 и gcc. Результат описан выше Попробовал написать класс реализующий методы инта: = и ++(int). Попробовал этот-же код с экземпляром этого класса, в результате, как и ожидалось x == 0. Либо мир сошел с ума, либо я. Люди помогите! |
Сообщ.
#2
,
|
|
|
x=x++ <=> x=x=x+1 =>x=x+1
Комментарии излишни |
Сообщ.
#3
,
|
|
|
Ну, сначала присвоение потом инкрементирование - все правильно. Обе операции ведь над одним оперндом.
|
Сообщ.
#4
,
|
|
|
А откомпилировав и запустив вот ето:
int main() { int x = 0, y = 0; x = y = x++; printf("%d, %d", x, y); } тоже скажете, что все правильно |
Сообщ.
#5
,
|
|
|
Получается 1 0
1) выполняется присвоения (x = y = 0) 2) выполняется инкремент (x = 1) IMHO нет никакого бага. |
Сообщ.
#6
,
|
|
|
Тут не однозначность, результат зависит от компилятора
|
Сообщ.
#7
,
|
|
|
А на каком компиляторе это не так, как я привел?
Я пользовался g++ 2.95.4 IMHO здесь все по стандарту. |
Сообщ.
#8
,
|
|
|
в том то и дело что неодначность по стандарту, я как раз читал это в книге где приводился пример неодназчности языка С. А компиляторов много.
|
Сообщ.
#9
,
|
|
|
В стандарте это называется behavior is unspecified
|
Сообщ.
#10
,
|
|
|
Цитата lunc @ 13.02.04, 19:23 Ну, сначала присвоение потом инкрементирование - все правильно. Обе операции ведь над одним оперндом. Посмотри Страуструпа, или MSDN: оператор постинкремента имеет такой-же приоритет как и ->, например. Оператор преинкремента имеет такой-же приоритет как sizeof. Это стандарт. Вопросы к Страуструпу почему так. Если-бы было так как ты говоришь, то перегруженный класс должен был-бы сработать так-же, но он сработал именно так как написано в стандарте, т.е. x++ сначала, а уж присвоение - потом. Спорить тут не о чем. Есть сомнения - загляни в старину Струпа - там все доходчего разъяснено. Короче, со стандартным типом при дизассемблировании видно, что порядок выполнения операторов нарушен. Сначала выполняется присвоение, а уж потом - постинкремент. Это, простите, баг. |
Сообщ.
#11
,
|
|
|
Когла я говорил про последовательность, я не имел ввиду приоритет, а последовательность команд.
Страуструп 6.2.5 (3-е издание): Цитата Например, y = x++ эквивалентно y=(t=x, x+=1, t) О последовательности операций в выражениях с инкрементами там ничего не говорится (ну, по крайней мере я не нашел, если есть - ткните, плз). В Лафоре довольно конкретно говорится, что постфиксный инкремент в выражениях всегда выполняется последним. Всегда так было, и выражение x = x++ - не исключение. Например, y = 2 * x++; выглядит как: Цитата mov eax, [ebp-0x34] add eax, eax mov [ebp-0x38, eax] inc dword ptr [ebp-0x34] Точно так же и x = x++; Цитата mov eax, [ebp-0x34] mov [ebp-0x38, eax] inc dword ptr [ebp-0x34] Пробовал компиляторы Borland и gcc - результат один. Если в каком-то компиляторе это не так, то в каком? |
Сообщ.
#12
,
|
|
|
x=x++; с точки рения логики неодназчен в 3.1 борланд С++ x не меняется как в других компилятарах я уже не писал подобное.
|
Сообщ.
#13
,
|
|
|
Цитата lunc @ 15.02.04, 03:32 Когла я говорил про последовательность, я не имел ввиду приоритет, а последовательность команд. А что такое "последовательность", по твоему? И зачем тогда нужен приоритет операции? Как раз по приоритетам команды в выражении и разбираются. Если в выходной последовательности порядок команд не соответствует приоритетам операций во входном выражении, всегда считалось что компиляция проведена с ошибками. |
Сообщ.
#14
,
|
|
|
В Страустропе сказано, что результат постфиксного инкремента - значение операнда. После того, как результат помечен осуществяется инкрементирование. Итого имеем 2 операции - присвоение (пометка операнда) и инкрементирование.
Цитата По идее - 0, в самом деле имеем: выполняется x++, и возвращает значение x до инкремента, а потом выполняется оператор =, присваивающий результат x++ переменной x Здесь три операции (что видно и из фссемблерного кода), а не две. Приоритет "++" выше "=". Получаем следующую последовательность: пометка текущего значения, присвоение и инкрементирование. Вопрос только в том, где считать, что "++" закончен и на какую часть операции инкрементирования распростараняется правило приоритета. Поэтому на практике предполагают, что приоритет инкремента завист от его типа - постфиксный или префиксный. |