Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Преобразование типов (char* в int) 
V
    Опции темы
NoviceF
Дата 23.7.2012, 21:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 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. Немного переделав получил следующее (наверно количество скобок излишне, но это чтобы не отвлекаться от основного вопроса):

Код

#include <iostream>

using std::cout;
using std::endl;

int main()
{
    char* pc = "qwer";
    
    cout << "pc = " << ((int)(pc))  << endl;
    cout << "string = " << ((int)("qwer"));
     
    return 0;
}


Первый вопрос в том, что именно приводится к 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) Почему программа ведёт себя так, как описано выше (не меняет вывод при изменении строки, на которую указывает указатель)?

Спасибо за ответы.
PM MAIL   Вверх
disputant
Дата 23.7.2012, 21:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 210
Регистрация: 28.11.2011

Репутация: нет
Всего: 3



Все просто, если понять, что первое и второе "qwer" находятся в памяти в разных местах...

Например, 

Код

char * s1 = "qwer";
char * s2 = "qwer";

s[1] = 't';

cout << s1 << endl;
cout << s2 << endl;


Если бы было так, как вы ожидаете, выведены были бы две одинаковые строки...
PM MAIL   Вверх
boostcoder
Дата 23.7.2012, 21:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 20
Всего: 110



disputant, такого делать нельзя.
во-первых - константную строку нельзя присваивать неконстантному указателю. компилятор ругаться будет.
во-вторых - при изменении исходной символьной строки через указатель - получаем SIGSEGV. пример: http://liveworkspace.org/code/30b127160fab...6a285fe179118f8 (после "ping" ничего не выводится ибо прога упала)

еще один интересный момент состоит в том, что обе строки будут расположены по одному адресу ;)

NoviceF, что-то ты сам себя путаешь.
разбей вопросы на маленькие детали. так проще будет.

PM WWW   Вверх
korian
Дата 23.7.2012, 21:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 651
Регистрация: 8.3.2008
Где: Украина, Харьков

Репутация: 2
Всего: 17



Цитата(NoviceF @  23.7.2012,  20:04 Найти цитируемый пост)
1) Что именно приводится к int?

Значение указателя.

Цитата(NoviceF @  23.7.2012,  20:04 Найти цитируемый пост)
Насколько я понимаю, должна та информация, которая содержится там, куда указывает указатель

Чтобы было так, надо писать: i = *(int*)pc;

Цитата(NoviceF @  23.7.2012,  20:04 Найти цитируемый пост)
2) Какой принцип при этом используется? (как получается значение 134515745)

Один к одному, если размер указателя не больше размера int. Если больше, то значение указателя обрезается.

Цитата(NoviceF @  23.7.2012,  20:04 Найти цитируемый пост)
3) Почему программа ведёт себя так, как описано выше (не меняет вывод при изменении строки, на которую указывает указатель)?


Цитата(NoviceF @  23.7.2012,  20:04 Найти цитируемый пост)
При одинаковых значениях  char* pc = "qwer" и  ((int)("qwer"))

Компилятор оптимизировал и положил строку "qwer" один раз. Поэтому значения указателей на обе строки одинаковые.

Цитата(NoviceF @  23.7.2012,  20:04 Найти цитируемый пост)
При изменении char* pc = "qwe" и сохранении  ((int)("qwer"))

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


PM   Вверх
boostcoder
Дата 23.7.2012, 21:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 20
Всего: 110



PM WWW   Вверх
NoviceF
Дата 23.7.2012, 22:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 313
Регистрация: 13.3.2012
Где: Ростов-на-Дону

Репутация: 2
Всего: 2



korian
boostcoder

Спасибо.
PM MAIL   Вверх
disputant
Дата 24.7.2012, 09:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 210
Регистрация: 28.11.2011

Репутация: нет
Всего: 3



Цитата(boostcoder @ 23.7.2012,  21:47)
disputant, такого делать нельзя.
во-первых - константную строку нельзя присваивать неконстантному указателю. компилятор ругаться будет.
во-вторых - при изменении исходной символьной строки через указатель - получаем SIGSEGV.

Это смотря где и с какими ключами компиляции smile

Возьмите что-то попроще, типа Open Watcom - прокатит на ура...

Сейчас, кстати, попробую...

Код

#include <iostream>
using namespace std;
int main(int argc, const char * argv[])
{
    char * s1 = "qwerty";
    char * s2 = "qwerty";
    cout << int(s1) << endl;
    cout << int(s2) << endl;
    s1[3] = '@';
    cout << s1 << endl;
    cout << s2 << endl;
}


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


PM MAIL   Вверх
boostcoder
Дата 24.7.2012, 09:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 20
Всего: 110



Цитата(disputant @  24.7.2012,  09:14 Найти цитируемый пост)
значит, работает некорректно

а разве когда-то было иначе?

Цитата(disputant @  24.7.2012,  09:14 Найти цитируемый пост)
Формально, насколько я помню, полагаться ни на тот, ни на этот  варианты (что это будет одна строка в памяти или разные) нельзя.

именно так.
но как правило - одинаковые.

Цитата(disputant @  24.7.2012,  09:14 Найти цитируемый пост)
 (это ведь он в LWS работает?)

да.

Цитата(disputant @  24.7.2012,  09:14 Найти цитируемый пост)
признал присвоение не ошибкой, а только ворнингом.

ну да. это сделано для обратной совместимости. ибо более старые версии GCC ничего против этого не имели.

PM WWW   Вверх
xvr
Дата 24.7.2012, 10:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Цитата(disputant @  24.7.2012,  09:14 Найти цитируемый пост)
И, значит, работает некорректно - раз позволяет присваивать const указателю на неконстантную строку, но после этого не работает. 

Вполне корректно - попытка модифицировать память по const указателю (после того, как const было принудительно снято) - UB. Так что имеет право и упасть  smile 

PM MAIL   Вверх
disputant
Дата 24.7.2012, 11:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 210
Регистрация: 28.11.2011

Репутация: нет
Всего: 3



[QUOTE=xvr,24.7.2012,  10:01]
Цитата(disputant @  24.7.2012,  09:14 Найти цитируемый пост)
Вполне корректно - попытка модифицировать память по const указателю (после того, как const было принудительно снято) - UB. Так что имеет право и упасть  smile

Если бы я написал

Код

char * s = (char*)"qwerty";


То не возражал бы. Но, например, 

Код

    const char * c = "qwerty";
    char * s = c;


даже OW не пропускает, вполне логично считая ошибкой.

И в этом смысле OW гораздо ПОСЛЕДОВАТЕЛЬНЕЕ (не пишу - правильнее, но последовательнее) - раз разрешил присваивание указателю на неконстантную строку. то разрешил и менять.

Остальные же, с варнингом (gcc) или вообще молча (VS) разрешают, и после этого падают. Так кто тут более логичен? smile

PM MAIL   Вверх
volatile
Дата 25.7.2012, 00:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Цитата(disputant @  24.7.2012,  11:02 Найти цитируемый пост)
 раз разрешил присваивание указателю на неконстантную строку. то разрешил и менять.

disputant, это просто совпадение. Где гарантии что при других ключах оптимизации, или, например, в следующей версии компилятора, это случайное поведение сохранится ?

Цитата(disputant @  24.7.2012,  09:14 Найти цитируемый пост)
Кстати, адреса s1 и s2 и в этом случае разные. Формально, насколько я помню, полагаться ни на тот, ни на этот  варианты (что это будет одна строка в памяти или разные) нельзя. 

В студии это регулируется ключом оптимизации.

Цитата(disputant @  24.7.2012,  09:14 Найти цитируемый пост)
Пробуем VS 2010...
Компилирует без вопросов, но при работе слетает. 

От вышеназванного ключа, зависит и реагирование на изменение константной памяти.
Что еще раз говорит о том что делать какие-то далеко идущие выводы на одном тестовом примере нельзя. 
Одним словом это UB, и этим все сказано.

Добавлено через 6 минут и 32 секунды
по изначальной теме. 
Цитата(NoviceF @  23.7.2012,  21:04 Найти цитируемый пост)
Преобразование типов (char* в int) 

Далеко не на всех платформах такое преобразование валидно.

PM MAIL   Вверх
disputant
Дата 25.7.2012, 06:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 210
Регистрация: 28.11.2011

Репутация: нет
Всего: 3



Цитата(volatile @ 25.7.2012,  00:39)
Где гарантии что при других ключах оптимизации, или, например, в следующей версии компилятора, это случайное поведение сохранится?

Да никакой!
Как нет никакой гарантии, что в следующей версии любой компилятор будет [полностью] соответствовать стандарту C++...  smile 



P.S. Старая математическая хохма - оценить вероятность того, что завтра Солнце взойдет в очередной раз, на основании того, что оно восходит по утрам 4 миллиарда лет...  smile 

P.P.S.
Цитата(volatile @ 25.7.2012,  00:39)
В студии это регулируется ключом оптимизации.

А я о чем:
Цитата(disputant @ 24.7.2012, 09:14)
Это смотря где и с какими ключами компиляции


Это сообщение отредактировал(а) disputant - 25.7.2012, 06:15
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0854 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.