![]() |
Модераторы: bsa |
![]() ![]() ![]() |
|
NoviceF |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 313 Регистрация: 13.3.2012 Где: Ростов-на-Дону Репутация: 2 Всего: 2 |
Здравствуйте.
Гугл и беглый поиск по форуму не помогли внести ясность. В процессе чтения Страуструпа возникли вопросы по данному примеру (3.2.5 Преобразование типа): int i = 1; char* pc = "asdf"; int* pi = &i; i = (int)pc; pc = (char*)i; pi = (int*)pc; pc = (char*)pi; У меня проблема с пониманием преобразования i = (int)pc. Немного переделав получил следующее (наверно количество скобок излишне, но это чтобы не отвлекаться от основного вопроса):
Первый вопрос в том, что именно приводится к int? Насколько я понимаю, должна та информация, которая содержится там, куда указывает указатель, но по факту, когда выполняешь этот код без строки "cout << "string = " << ((int)("qwer"))" изменение содержимого преобразуемой строки не влияет на вывод. Второй непонятный момент состоит в том, что при выполнении кода в таком виде, при изменении строки, на которую указывает char* pc, её вывод не меняется, но меняется вывод ((int)("qwer")): При одинаковых значениях char* pc = "qwer" и ((int)("qwer")) Execution output: pc = 134515745 string = 134515745 При изменении char* pc = "qwe" и сохранении ((int)("qwer")) Execution output: pc = 134515745 string = 134515755 http://liveworkspace.org/code/84c7db3d5264...4a9ee3bfd151287 Ну и вопросы: 1) Что именно приводится к int? 2) Какой принцип при этом используется? (как получается значение 134515745) 3) Почему программа ведёт себя так, как описано выше (не меняет вывод при изменении строки, на которую указывает указатель)? Спасибо за ответы. |
|||
|
||||
disputant |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 210 Регистрация: 28.11.2011 Репутация: нет Всего: 3 |
Все просто, если понять, что первое и второе "qwer" находятся в памяти в разных местах...
Например,
Если бы было так, как вы ожидаете, выведены были бы две одинаковые строки... |
|||
|
||||
boostcoder |
|
|||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 20 Всего: 110 |
disputant, такого делать нельзя.
во-первых - константную строку нельзя присваивать неконстантному указателю. компилятор ругаться будет. во-вторых - при изменении исходной символьной строки через указатель - получаем SIGSEGV. пример: http://liveworkspace.org/code/30b127160fab...6a285fe179118f8 (после "ping" ничего не выводится ибо прога упала) еще один интересный момент состоит в том, что обе строки будут расположены по одному адресу ;) NoviceF, что-то ты сам себя путаешь. разбей вопросы на маленькие детали. так проще будет. |
|||
|
||||
korian |
|
||||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 651 Регистрация: 8.3.2008 Где: Украина, Харьков Репутация: 2 Всего: 17 |
Значение указателя.
Чтобы было так, надо писать: i = *(int*)pc;
Один к одному, если размер указателя не больше размера int. Если больше, то значение указателя обрезается.
Компилятор оптимизировал и положил строку "qwer" один раз. Поэтому значения указателей на обе строки одинаковые. это компилятор оптимизировать не может, поэтому есть 2 строки, с разными значениями указателей. |
||||||
|
|||||||
boostcoder |
|
|||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 20 Всего: 110 |
||||
|
||||
NoviceF |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 313 Регистрация: 13.3.2012 Где: Ростов-на-Дону Репутация: 2 Всего: 2 |
korian,
boostcoder, Спасибо. |
|||
|
||||
disputant |
|
||||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 210 Регистрация: 28.11.2011 Репутация: нет Всего: 3 |
Это смотря где и с какими ключами компиляции ![]() Возьмите что-то попроще, типа Open Watcom - прокатит на ура... Сейчас, кстати, попробую...
qwe@ty qwerty Пробуем VS 2010... Компилирует без вопросов, но при работе слетает. Значит, этот таки сует в r/o... И, значит, работает некорректно - раз позволяет присваивать const указателю на неконстантную строку, но после этого не работает. Кстати, адреса s1 и s2 и в этом случае разные. Формально, насколько я помню, полагаться ни на тот, ни на этот варианты (что это будет одна строка в памяти или разные) нельзя. Ага, только gcc (это ведь он в LWS работает?) выдал одинаковые адреса. Но признал присвоение не ошибкой, а только ворнингом... Вобщем, недаром была написана целая (кстати, очень интересная) книга "Неидеальный C++"... Так сказать "Grau, teurer Freund, ist alle Theorie. Und grün des Lebens goldner Baum." (с) von Goethe |
||||
|
|||||
boostcoder |
|
|||
![]() pattern`щик ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5458 Регистрация: 1.4.2010 Репутация: 20 Всего: 110 |
а разве когда-то было иначе?
именно так. но как правило - одинаковые. да. ну да. это сделано для обратной совместимости. ибо более старые версии GCC ничего против этого не имели. |
|||
|
||||
xvr |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 7046 Регистрация: 28.8.2007 Где: Дублин, Ирландия Репутация: 35 Всего: 223 |
Вполне корректно - попытка модифицировать память по const указателю (после того, как const было принудительно снято) - UB. Так что имеет право и упасть ![]() |
|||
|
||||
disputant |
|
||||||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 210 Регистрация: 28.11.2011 Репутация: нет Всего: 3 |
[QUOTE=xvr,24.7.2012, 10:01]
Если бы я написал
То не возражал бы. Но, например,
даже OW не пропускает, вполне логично считая ошибкой. И в этом смысле OW гораздо ПОСЛЕДОВАТЕЛЬНЕЕ (не пишу - правильнее, но последовательнее) - раз разрешил присваивание указателю на неконстантную строку. то разрешил и менять. Остальные же, с варнингом (gcc) или вообще молча (VS) разрешают, и после этого падают. Так кто тут более логичен? ![]() |
||||||
|
|||||||
volatile |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2107 Регистрация: 7.1.2011 Репутация: 16 Всего: 85 |
disputant, это просто совпадение. Где гарантии что при других ключах оптимизации, или, например, в следующей версии компилятора, это случайное поведение сохранится ? В студии это регулируется ключом оптимизации.
От вышеназванного ключа, зависит и реагирование на изменение константной памяти. Что еще раз говорит о том что делать какие-то далеко идущие выводы на одном тестовом примере нельзя. Одним словом это UB, и этим все сказано. Добавлено через 6 минут и 32 секунды по изначальной теме. Далеко не на всех платформах такое преобразование валидно. |
||||
|
|||||
disputant |
|
||||||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 210 Регистрация: 28.11.2011 Репутация: нет Всего: 3 |
Да никакой! Как нет никакой гарантии, что в следующей версии любой компилятор будет [полностью] соответствовать стандарту C++... ![]() P.S. Старая математическая хохма - оценить вероятность того, что завтра Солнце взойдет в очередной раз, на основании того, что оно восходит по утрам 4 миллиарда лет... ![]() P.P.S.
А я о чем:
Это сообщение отредактировал(а) disputant - 25.7.2012, 06:15 |
||||||
|
|||||||
![]() ![]() ![]() |
Правила форума "C/C++: Для новичков" | |
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Для новичков | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |