c++pointersdeclarationoperator-precedence

Operator Precedence in declaring more pointers in one instruction


I would like to understand why do i have to add an asterisk before each identifier when declaring more pointers with the same datatype on the same row.

Here is where i read from


Another thing that may call your attention is the line:

int * p1, * p2;

This declares the two pointers used in the previous example. But notice that there is an asterisk (*) for each pointer, in order for both to have type int* (pointer to int). This is required due to the precedence rules. Note that if, instead, the code was:

int * p1, p2;

p1 would indeed be of type int*, but p2 would be of type int. Spaces do not matter at all for this purpose. But anyway, simply remembering to put one asterisk per pointer is enough for most pointer users interested in declaring multiple pointers per statement. Or even better: use a different statement for each variable.


The operator precedence

The question: What rule is used here, what precedence is this? It is about comma or asterisk? I can't figure it out.


Solution

  • There is no any precedence rule. The gramma of a simple declaration looks like

    decl-specifier-seq init-declarator-listopt ; 
    

    The sign * belongs to declarators not to decl-specidier-seq as for example type specifier int.

    So you may for example rewrite the declaration

    int * p1, * p2;
    

    like

    int ( * p1 ), ( * p2 );
    

    where ( *p1 ) and ( *p2 ) are decalartors (thouhg in this case the parentheses are redundant)

    You may not write for example

    ( int * ) p1, p2;
    

    The compiler will issue an error.

    Parentheses are required when a more complicated type is declared. For example let's declare a pointer to an array

    int ( *p )[N];
    

    where N is some constant.

    So you may enclose declarators in parentheses.

    Let's consider a more complicated declaration: of a function that returns a pointer to function and has as a parameter another function

    void ( *f( int cmp( const void *, const void * ) )( int *a );
    

    As for the precedence then rules of building declarators describe them in the gramma

    For example

    if you will write

    int * a[10];
    

    then it is an array of 10 elements of the type int *.

    However if you will write

    int ( *a[10] ); 
    

    then its an array of 10 pointers to objects of the type int.

    If you will write

    int ( *a )[10];
    

    then it is a pointer to an array of 10 integers.

    Take into account that typedef is also a decl-specifier.

    So for example this typedef

    typedef int *intPtr;
    

    you may rewrite like

    int typedef *intPtr;
    

    or even like

    int typedef ( *intPtr );
    

    One more example of declaration. Let's consider a multidimensional array. In can be declared like

    int ( ( ( a )[N1] )[N2] );
    

    though again the parentheses are redundant. However they can help to understand how arrays are implicitly converted to pointers to their first elements in expressions.

    For example if you have an array

    int a[N1][N2];
    

    then to get a pointer declaration to its first element you can rewrite the declaration ,like

    int ( a[N1] )[N2];
    

    and now substitute a[N1] for *a (or for example *p).

    int ( *p )[N2] = a;