Страницы

Поиск по вопросам

понедельник, 29 октября 2018 г.

Указатель на тип char

Я как-то давно спрашивал по поводу указателей, разобрался, всем ответившим спасибо. Но сейчас мне пришлось столкнутся с типом char
int *a; char *b;
a = new int(10); b = "bla bla bla"; // Странно ведь мы записываем в адрес, а не в разыменованный указатель
cout << "a: " << *a << endl; // Выведет значение, а без * адрес (логично и понятно) cout << "b: " << b << endl; // Выведет значение всего того что мы засунули в "адрес" указателя, почему так, если приводить аналогию с int то почему тут не как там?
Хотелось бы понять, как работает указатель на тип char (хотелось бы увидеть аргументированные ответы, почему так различается, и что-то от себя как рекомендации). Шерстил интернет — по теме указателей в C++ ничего не нашел
P. S.: Прошу прощения, если эта тема всех достала или мое сообщение является дубликатом (есть темы похожие, но, вроде, это не то, что мне надо).


Ответ

Давайте рассмотрим предложения из вашего примера шаг за шагом.
В этом предложении
int *a;
вы объявили переменную a как указатель на объект с типом int
В этом предложении
char *b;
вы объявили переменную b как указатель на объект с типом char
В этом предложении
a = new int(10);
был создан объект в динамической памяти типа int, который был инициализирован значением 10.
В этом предложении
b = "bla bla bla";
в левой части выражения с оператором присваивания стоит переменна с типом char *. В правой части этого выражения используется строковый литерал "bla bla bla". Строковые литералы в C++ имеют типы константных символьных массивов.
(C++ Стандарт, 2.14.5 String literals)
8 Ordinary string literals and UTF-8 string literals are also referred to as narrow string literals. A narrow string literal has type “array of n const char”, where n is the size of the string as defined below, and has static storage duration (3.7).
Строковый литерал "bla bla bla" имеет тип const char [12]. В выражениях массивы неявно преобразуются к указателям на свой первый элемент.
Согласно стандарту C++ (4.2 Array-to-pointer conversion)
1 An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. The result is a pointer to the first element of the array
Таким образом в приведенном предложении в правой части выражения с оператором присваивания используется значение типа const char *, которое указывает на первый символ строкового литерала "bla bla bla". То есть имеет место попытка указателю типа char * присвоить значение указателя типа const char *. Так как не существует неявного преобразования из типа указателя на константный объект в тип указателя на неконстантный объект, то компилятор должен выдать диагностическое сообщение.
Правильно было бы объявить переменную b следующим образом
const char *b;
Тогда вышеприведенное предложение с присваиванием было бы корректно, и переменной b был бы присвоен адрес первого символа строкового литерала, стоящего в правой части выражения от знака присваивания.
Данное предложение
b = "bla bla bla";
фактически, эквивалентно следующему предложению
b = &"bla bla bla"[0];
В этом предложении
cout << "a: " << *a << endl;
целочисленное значение, адресуемое указателем a выводится на консоль.
Было бы более корректно записать
cout << "*a: " << *a << endl; ^^^
В этом предложении
cout << "b: " << b << endl;
при условии, что компилятор каким-то образом сгенерировал объектный модуль, несмотря на ошибку, о которой я сказал выше, выведет на консоль строковый литерал, так как для указателей типа char * оператор operator << перегружен таким образом, что вместо значения самого указателя, он выводит содержимое памяти, адресуемое этим указателем, как строку.
Если вы хотите вывести на консоль именно значение самого указателя, то вам в таком случае следует написать либо
cout << "b: " << ( void * )b << endl;
либо
cout << "b: " << static_cast( b ) << endl;
А если переменная b была объявлена с квалификатором const, то
cout << "b: " << ( const void * )b << endl;
либо
cout << "b: " << static_cast( b ) << endl;

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

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