What does a const pointer-to-pointer mean in C and in C++?

I know the rule-of-thumb to read declarations right-to-left and I was fairly sure I knew what was going on until a colleague told me that:

const MyStructure** ppMyStruct;

means "ppMyStruct is a pointer to a const pointer to a (mutable) MyStructure" (in C++).

I would have thought it meant "ppMyStruct is a pointer to a pointer to a const MyStructure". I looked for an answer in the C++ spec, but apparently I'm not very good at that...

What does in mean in C++, and does it mean the same thing in C?


ANSWERS:


Your colleague is wrong. That is a (non-const) pointer to a (non-const) pointer to a const MyStructure. In both C and C++.


In such cases the tool cdecl (or c++decl) can be helpfull:

     [flolo@titan ~]$ cdecl explain "const struct s** ppMyStruct"
     declare ppMyStruct as pointer to pointer to const struct s

You were right in your interpretation. Here's another way to look at it:

const MyStructure *      *ppMyStruct;        // ptr --> ptr --> const MyStructure
      MyStructure *const *ppMyStruct;        // ptr --> const ptr --> MyStructure
      MyStructure *      *const ppMyStruct;  // const ptr --> ptr --> MyStructure

These are all the alternatives of a pointer-to-pointer with one const qualifier. The right-to-left rule can be used to decipher the declarations (at least in C++; I'm no C expert).


You are right.

Another answer already pointed to the "Clockwise Spiral Rule". I liked that one very much - a little elaborate, though.


Your colleague is wrong, and it's the same for C and C++. Try the following:

typedef struct foo_t {
    int i;
} foo_t;

int main()
{
    foo_t f = {123};
    const foo_t *p = &f;
    const foo_t **pp = &p;
    printf("f.i = %d\n", (*pp)->i);
    (*pp)->i = 888; // error
    p->i = 999;     // error
}

Visual C++ 2008 gives the following errors for the last two lines:

error C2166: l-value specifies const object
error C2166: l-value specifies const object

GCC 4 says:

error: assignment of read-only location '**pp'
error: assignment of read-only location '*p'

G++ 4 says:

error: assignment of data-member 'foo_t::i' in read-only structure
error: assignment of data-member 'foo_t::i' in read-only structure

As a corollary to the other comments, don't put 'const' first. It really belongs after the type. That would have clarified the meaning immediately, just read it RTL as usual:

MyStructure const** ppMyStruct;

void Foo( int       *       ptr,
          int const *       ptrToConst,
          int       * const constPtr,
          int const * const constPtrToConst )
{
    *ptr = 0; // OK: modifies the pointee
    ptr  = 0; // OK: modifies the pointer

    *ptrToConst = 0; // Error! Cannot modify the pointee
    ptrToConst  = 0; // OK: modifies the pointer

    *constPtr = 0; // OK: modifies the pointee
    constPtr  = 0; // Error! Cannot modify the pointer

    *constPtrToConst = 0; // Error! Cannot modify the pointee
    constPtrToConst  = 0; // Error! Cannot modify the pointer
}


 MORE:


 ? What is a long pointer?
 ? What is the point of function pointers?
 ? What do people find difficult about C pointers?
 ? C++: What are scenarios where using pointers is a "Good Idea"(TM)?
 ? What does "dereferencing" a pointer mean?
 ? What exactly is a C pointer if not a memory address?
 ? What is the best way to create a sparse array in C++?
 ? What is the best way to create a sparse array in C++?
 ? What is the best way to create a sparse array in C++?
 ? Good C++ array class for dealing with large arrays of data in a fast and memory efficient way?