|
Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Помогите начинающему понять оператор Си++ |
|
Помогите начинающему понять оператор Си++
|
Guest |
Никак не понимаю как работает такая фича, как косвенная модификация.
Вот код: #include <iostream> #include <stdlib> int main(void) { int const var = 1; int const* pVar = &var; cout << "var = " << var << " *pVar = " << *pVar << endl; *(int*)pVar = 2; cout << "var = " << var << " *pVar = " << *pVar << endl; *(int*)&var = 3; cout << "var = " << var << " *pVar = " << *pVar << endl; system("PAUSE" return 0; } В результате дает: var = 1 *pVar = 1 var = 1 *pVar = 2 var = 1 *pVar = 3 Но что это за дела? Это же однин локальный указатель, как он может такое показывать, если в себе содержит просто адрес var? И, собственно, что значит сам оператор *(int*)pVar = 2;? Вроде похоже на приведение типа, но как-то необычно... Или вроде pVar приводится к int*, а затем, еще звездочка перед этим всем, чтобы можно было присвоить новое значение переменной на которую он ссылается? Дык переменная не изменяется! Тогда, *(int*)&var = 3; - ячейки начиная с адреса &var приводятся к типу указателя на int, и эти ячейки затем разиминовываются. Короче, нифега не понятно. А думать самому лень :-), так что может кто более опытный подскажет что это все такое :-). Вопросы такие: 1. Что занчит *(int*)pVar = 2; 2. Что занчит *(int*)&var = 3; 3. И почему, черт возьми, указатель показывает что var равна 3, когда она равна 1?? |
|
Отправлено: 00:33, 10-10-2004 |
редкий гость Сообщения: 1696
|
Профиль | Сайт | Отправить PM | Цитировать Всё очень просто, т.к. переменная var объявлена как константа, то компилятор делает логичное (и, самое главное, законное) предположение, что она не изменяется и всегда равна 1. Производится соответствующая оптимизация (т.е. вместо того что бы обращаться к ячейке памяти и получать заведомую единицу, компилятор сразу кладёт 1 на стек). Почему же под переменную var вообще выделяется память? Да потому, что компилятор видит, что берётся адрес этой переменной, а указателю надо на что-то указывать. Если бы адрес не брался, память можно было бы и не выделять вообще, и это было бы вполне законно.
В то же время, поскольку память под эту константную переменную выделяется. То pVar (и &var) указывает на эту память. Дргое дело, что pVar - указатель на _константу_ и то, на что он указывает изменять нельзя. В вашей программе это обходится сишным приведением типов, которое может снимать константность. Того же можно добиться используя const_cast. Но! const_cast, так же как и и сишное приведение, является грязным хаком. Поэтому пользоваться им можно только в исключительных случаях. Попробуйте скомпилировать ваш пример без оптимизации, результат вполне может поменться. Цитата:
Цитата:
А теперь страшное предположение: вам предложил препод эту задачу на сообразительность, посулив лёгкий зачёт или, чем чёрт не шутит, - экзамен автоматом. Вы как тупой студент, который не желает разбираться сам задали этот вопрос здесь. Почему я так считаю? Просто человек, кторый не знает что такое сишное приведение типов не смог бы написать программу, использующую его. Таково уж моё мнение. Если я ошибся, то готов принести свои извинения. Хотя, сомневаюсь, что мне придётся это делать. |
||
------- Отправлено: 01:50, 10-10-2004 | #2 |
Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети. Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля. |
Guest |
Вроде, понял. Есть две переменные. Та, в памяти, которая оставлена для указателя, и та, которая в стеке, похоже, для ускорения доступа.
Следовательно, если компилить без оптимизации, то переменная будет только одна, и var = 3 *pVar = 3. =========================================== Я просто первый раз встречаюсь с таким приемом, как снятие константности с помощью сишного привидения типов. А теперь вроде дошло. Это выражение: *(int*)pVar = 2; можно прочесть как привести значение константной переменной, на которую ссылается pVar, к типу int (во время это операции снимается константность) и присвоеть ей единицу. Просто по правилу, в роде надо написать было (int*)*pVar = 2; - это меня и смутило. Почему не записано так? При этом варианте, компилятор пишет,что не может изменить значение константного объекта. Я думаю, может все дело в этапах. При (int*)*pVar = 2; варианте в первом этапе идет приведние типа. А потом попытка изменить консанту[ 1. (int*) 2. *pVar = 2;]. А при *(int*)pVar = 2; все идет в один этап. Переменная на которую ссылается указатель, приводится к типу int (потому и звездочка раньше)и сразу изменяется, а уже потом объявляется константой. Я верно предположил??? А теперь действительно страшное предположение . Я учусь в 11-м классе, и, как говорится, от скуки на все руки. Вот и играюсь с Си++. А Си++ учу сам по книжкам. Цитата:
|
|
Отправлено: 03:57, 10-10-2004 | #3 |
Guest |
Ура, все дошло !
1. C указателя на константу снимается константность. 2. Он разименовывается. 3. Ячейке памяти, на которую он указывает присваивается 2-ка. 1. (int*)pVar 1. const_cast<int*>(pVar) 2. *(int*)pVar 2. *const_cast<int*>(pVar) 3. *(int*)pVar = 2; 3. *const_cast<int*>(pVar) = 2; |
Отправлено: 14:02, 10-10-2004 | #4 |
редкий гость Сообщения: 1696
|
Профиль | Сайт | Отправить PM | Цитировать Цитата:
В общем-то, в последнем почте всё правильно написано, так что комментировать больше нечего. |
||
------- Отправлено: 18:56, 11-10-2004 | #5 |
Участник сейчас на форуме | Участник вне форума | Автор темы | Сообщение прикреплено |
| |||||
Название темы | Автор | Информация о форуме | Ответов | Последнее сообщение | |
Помогите начинающему!!! | Kanonir | Программное обеспечение Linux и FreeBSD | 21 | 19-03-2007 12:26 | |
Помогите начинающему! | xden777 | Вебмастеру | 4 | 06-03-2006 16:53 | |
Помогите начинающему | curbat | Общий по Linux | 6 | 17-05-2004 09:02 | |
Помогите начинающему | Guest | Общий по Linux | 6 | 05-04-2004 13:41 | |
помогите начинающему | Guest | Общий по Linux | 9 | 05-03-2004 15:07 |
|