Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Проблема с приоритетами унарных операций


Автор: voyageur 27.2.2009, 16:51
Здравствуйте! Подскажите, пожалуйста, как исправить?
Код

#include<iostream>
using namespace std;
void main()
{
 int i1=10, i2=20, i3=30;
int *p=&i2;
//Значение i2
cout <<"\n *&i2 = "<< *&i2;
//Значение i2 сначала увеличенное на 1
cout <<"\n *&++i2 = "<< *&++i2;
//Значение i2
cout <<"\n *p = "<< *p;
//Значение i2,  p увеличивается на 1
cout <<"\n *p++ = "<< *p++;
//Значение i1
cout <<"\n *p = "<< *p;
//Значение i1 сначала увеличенное на 1
cout <<"\n ++*p = "<<++*p;
//Значение i2, сначала уменьшается p
cout <<"\n *--p = "<<*--p;
//Значение i3, сначала уменьшается p, затем полученное значение i3 
//увеличивается
cout <<"\n ++*--p = "<<++*--p;
}


Результат должен быть:
Код

*&i2 = 20
   *&++i2 = 21
   *p = 21
   *p++ = 21
   *p = 10
   ++*p = 11
   *--p = 21
   ++*--p = 31

Но при отладке вылазит ошибка Run-Time Check Failure #2 - Stack around the variable 'i2' was corrupted.
и результат работы:

  
Код

*&i2 = 20
 *&++i2 = 21
 *p = 21
 *p++ = 21
 *p = -858993460
 ++*p = -858993459
 *--p = 21
 ++*--p = -858993459

использую VS 2005

Автор: pan2004 27.2.2009, 18:09
voyageur, кто сказал, что после инкрементирования указателя он будет указывать на другую переменную(i1)? В release версии такое возможно и сработает, но является грязным хаком, так что UB(порча стека) - закономерный результат неправомерных действий.

Автор: voyageur 27.2.2009, 19:52
pan2004, это нас в институте такому учат, прям вот как препод на доске написал так и есть. То есть нельзя чтоли таким образом адрес изменять? должно перейти на i1 т.к. в памяти оно хранится перед i2, то есть адрес переменной i2 - 1 будет i1 а если i2 +1 то будет i3. Разве нет?

Автор: pan2004 27.2.2009, 21:11
Цитата(voyageur @  27.2.2009,  19:52 Найти цитируемый пост)
Разве нет?

Нет. Скорее всего ты не сможешь найти в стандарте места, который оговаривает такое поведение.
В дебаг режиме компилятор(VS) судя по всему "окаймляет" каждую стековую переменную специальными метками. Во время выполнения проверяется целостность этих меток, а так как они повреждены(твоим блуждающим указателем), это идентифицируется как stack damage(то же самое касается и "кучи" в режиме дебага). Подобный механизм позволяет в дебаг версии быстро отловить ошибки типа выхода за границы массива. 
В релиз версии подобные метки ставится не должны, так что твоя программа может даже работать. Но не стоит на это полагаться. В настоящих программах строго рекомендую не пользоваться подобными уловками.

Автор: vinter 27.2.2009, 21:27
Цитата(voyageur @  27.2.2009,  20:52 Найти цитируемый пост)
прям вот как препод на доске написал так и есть

значит препод баран. Не слушай его в дальнейшем.

Автор: cutwater 27.2.2009, 21:47
Цитата(pan2004 @  27.2.2009,  20:11 Найти цитируемый пост)
то же самое касается и "кучи" в режиме дебага


pan2004, сегодня столкнулся с багом у себя в программе по этой части. компилятор cl (Visual Studio 2008)
подобного поведения не заметил. ошибка - обнуление памяти большего размера чем выделено( выделение при помощи оператора new), как проявлялось - bad_alloc exception при последующем выделении памяти.
В релиз версии не проверял, но имхо это поведение не похоже на описанное выше.

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

Автор: mes 27.2.2009, 22:09
Цитата(voyageur @  27.2.2009,  18:52 Найти цитируемый пост)
это нас в институте такому учат, прям вот как препод на доске написал так и есть

может это относилось к функции типа void f(...); (с переменным кол-вом аргументов) ? только в этом случае есть необходимость и возможность перебирать параметры "вручную" по указателю.

Автор: voyageur 28.2.2009, 01:10
pan2004, спасибо за полный ответ.

mes, нет, такой код нашел в сети: http://it.kgsu.ru/C++/c0018.html пример 3. 

Автор: cutwater 28.2.2009, 02:04
Цитата(voyageur @  28.2.2009,  00:10 Найти цитируемый пост)
такой код нашел в сети: http://it.kgsu.ru/C++/c0018.html пример 3.  


Убивать нужно за такое (творчество).

Автор: mes 28.2.2009, 11:15
Цитата(voyageur @  28.2.2009,  00:10 Найти цитируемый пост)
mes, нет, такой код нашел в сети: http://it.kgsu.ru/C++/c0018.html пример 3.  

Цитата(Козьма Прутков)

Если на клетке слона прочтешь надпись "буйвол", не верь глазам своим. 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)