Страницы

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

среда, 3 октября 2018 г.

Что означает const*?

Именно со звездой - демонические конструкции могут принимать вид
const char* const* blah_blah,
char const* blah
int const* const integer,
int* const* const и так далее в самых разных комбинациях. Как расшифровать сии начертания и зачем вообще может кому-то понадобиться оборачиваться в const, будто шелкопряду?


Ответ

Такие записи проще всего рассматривать справа налево. Например,
Данное объявление
const char * const * blah_blah;
объявляет указатель с именем blah_blah, который указывает на константный указатель (так как квалификатор const предшествует *, если смотреть справа налево), который указывает на константный объект типа char.
Вот пример простой программы, который облегчает понимание этого объявления.
#include
int main(void) { const char * const * blah_blah; const char *p = "Hello"; blah_blah = &p; puts( *blah_blah ); }
На консоль будет выведено
Hello
Можно ввести typedef имена для наглядности
typedef const char CONST_CHAR_TYPE; typedef CONST_CHAR_TYPE *POINTER_TO_CONST_CHAR_TYPE;
const POINTER_TO_CONST_CHAR_TYPE *blah_blah;
в этом случае переменная blah_blah является указателем на константный указатель на константный объект типа char
Я думаю будет легче понять эти объявления, если следовать грамматике определения указателя.
Указатель в стандарте C определяется следующим образом
pointer: * type-qualifier-listopt * type-qualifier-listopt pointer
то есть за знаком * может следовать список квалификации, который к нему относится.
Поэтому предыдущее объявление можно записать как
const char ( * const ( *blah_blah ) );
Можно сделать и сам указатель blah_blah константным. Но тогда он должен быть явно инициализирован при объявлении, если имеет автоматическую продолжительность памяти. Например
const char ( * const ( * const blah_blah ) ) = /* некоторое значение */;
или
const char * const * const blah_blah = /* некоторое значение */;
Вот демонстрационная программа, в которой сам указатель blah_blah также объявлен как константный.
#include
int main(void) { const char *p = "Hello"; const char ( * const ( * const blah_blah ) ) = &p; puts( *blah_blah ); }
Объявление этого указателя читается как константный указатель на константный указатель на константный объект типа char
В объявления функций, имеющих прототип, можно опускать идентификатор параметра.
Ниже представлена такая программа
#include
void display( const char ( * const ( * const ) ) ); void display( const char * const * const ); void display( const char ( * const ( * ) ) ); void display( const char * const * );
int main(void) { const char *p = "Hello"; display( &p ); }
void display( const char * const * const blah_blah ) { puts( *blah_blah ); }
Так как объявлений одной и той же функции (без ее определения) может быть несколько, то все выше указанные функции объявляют одну и ту же функцию. Так называемый квалификатор верхнего уровня, который относится непосредственно к параметру, можно убрать из объявления функции. То есть (еще один пример) эти пары функций объявляют одни и те же функции
void f( const int x ); void f( int x );
и
void g( int * const p ); void g( int * p );

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

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