понедельник, 14 сентября 2009 г.

char* и строковые литералы

Изучаю дальше.

char c = 'x';
char* pc = &c;

Все понятно, pc – указатель на переменную char. И тут внезапно! Оказывается можно так:

char* pc = ”Hello”;
cout << pc //Hello;

pc же вроде должна хранить адрес! Страуструп сказал, что так можно типа потому, что в языке C строковые литералы (это оказывается так по-научному называется) хранились именно так, через char*. А C++ должен поддерживать C. И Страуструпу тут все понятно и незачем останавливаться на этом подробно. Жаль я не он, и мне ничего не понятно. Мне не нравится, что char* ведет двойную жизнь. Сейчас будем разбираться.

Попробую посмотреть адрес, и разыменовать pc.

cout << pc << (long)pc << *pc; //Hello 4464640 H

Ага, pc выдает Hello, а когда я преобразовал ее к long, то она все-таки вернула адрес.
Отлично, *pc выдает символ H. Т.е. pc по-прежнему работает как указатель на char.
Интересно, где остальные символы слова.

Итак, я взял pc (а он все-таки хранит адрес, но при удобной возможности прикидывается строкой), прибавил к хранящемуся (слово было выговорено с только нескольких попыток) там адресу 1. В ячейке с адресом pc лежит ‘H’, очевидно предположить, что в следующей ячейке лежит 'e'. Чтобы узнать адрес следующей ячейки, нужно просто прибавить 1 (так как ячейка char равна байту). А чтобы извлечь ее значение, нужно сделать разыменование:

cout << *pc << *(pc+1) << *(pc+2) << *(pc+3) << *(pc+4); //Hello

Сейчас нарисую, память после:
char* pc = ”Hello”;
char* pc2 = ”World”;


Так получилось, что слова идут друг за другом. В следующий раз такого может не быть. Для этого случая верно выражение pc + 6 == pc2. Еще можно вытащить слово “World” не используя pc2

cout << *(pc+6) << *(pc+7) << *(pc+8) << *(pc+9) << *(pc+10); //World

Разумеется, в другой раз это может не прокатить.
Определить конец слова помогает ‘\0’. Если бы я был составителем задачника, то добавил задачу печати слова, используя *(pc+i) в цикле, пока не встретится ‘\0’.

А еще минздрав предупреждает: строковые литералы изменять нельзя. *(pc) = 'z'; вывалится с ошибкой во время выполнения.

Вообще говоря это устаревший способ, лучше использовать char c[] = “Hello”. Потом об этом напишу.

Комментариев нет:

Отправить комментарий

Можно использовать теги <b>, <i>