views:

2872

answers:

7

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?

+20  A: 

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

James Hopkin
It's also part of the reason you will sometimes see the alternative "spelling recommended: MyStructure const * *ppMyStruct; Then you can read right-to-left: pointer to pointer to const Mystructure.
MadKeithV
+20  A: 

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
flolo
Very useful. Why isn't this tool well-known?
David Holm
Do you happen to know if it's available for windows?
Niklas
It is open source and afaik it doesnt have any specific requirements to the OS. When lucky it should be compileable with any compiler, in worst case you have to use the gcc/cygwin or mingw stuff.
flolo
Great tip. Thanks!
unclerojelio
@Niklas : It's available online at http://www.cdecl.org/
nXqd
+4  A: 

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
csl
Why is this downvoted? I just thought it was better to give a specific example, instead of just telling him that he is right.
csl
guess it was a Visual C++ hater, GNU C++ lover :-)
dmityugov
Doesn't answer the question
Dynite
+1  A: 

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).

efotinis
A: 

You are right.

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

xtofl
+3  A: 

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;
MSalters
I fail to see how that makes it clearer, but I suppose it's a matter of habit.If the const comes first, I find it just as easy to read it RTL as "a pointer to a pointer to a MyStructure which is const".
Niklas
+3  A: 
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
}
dman
I don't see how this is an answer to the question. Did you misread it?
Niklas