Such records are most easily viewed from right to left. For example,
This announcement
const char * const * blah_blah;
declares a pointer named blah_blah , which points to a constant pointer (since the const qualifier is preceded by *, when viewed from right to left), which points to a constant object of type char .
Here is an example of a simple program that makes it easier to understand this ad.
#include <stdio.h> int main(void) { const char * const * blah_blah; const char *p = "Hello"; blah_blah = &p; puts( *blah_blah ); }
The console will display
Hello
You can enter typedef names for clarity
typedef const char CONST_CHAR_TYPE; typedef CONST_CHAR_TYPE *POINTER_TO_CONST_CHAR_TYPE; const POINTER_TO_CONST_CHAR_TYPE *blah_blah;
in this case, the variable blah_blah is a pointer to a constant pointer to a constant object of type char .
I think it will be easier to understand these declarations if you follow the grammar of the pointer definition.
The pointer in standard C is defined as follows.
pointer: * type-qualifier-listopt * type-qualifier-listopt pointer
that is, the list of qualifications that apply to it may follow the * sign.
Therefore, the previous announcement can be written as
const char ( * const ( *blah_blah ) );
You can make the pointer blah_blah constant. But then it must be explicitly initialized when it is declared, if it has an automatic memory duration. for example
const char ( * const ( * const blah_blah ) ) = /* некоторое значение */;
or
const char * const * const blah_blah = /* некоторое значение */;
Here is a demo program in which the blah_blah pointer blah_blah also declared as constant.
#include <stdio.h> int main(void) { const char *p = "Hello"; const char ( * const ( * const blah_blah ) ) = &p; puts( *blah_blah ); }
The declaration of this pointer is read as a constant pointer to a constant pointer to a constant object of type char .
In the function declarations having a prototype, you can omit the parameter identifier.
Below is such a program.
#include <stdio.h> 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 ); }
Since there can be several declarations of the same function (without its definition), all the above functions declare the same function. The so-called top-level qualifier that relates directly to a parameter can be removed from the function declaration. That is (another example) these pairs of functions declare the same functions.
void f( const int x ); void f( int x );
and
void g( int * const p ); void g( int * p );