42

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?

xsl
  • 17,116
  • 18
  • 71
  • 112
Niklas
  • 5,736
  • 7
  • 35
  • 42

7 Answers7

67

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
  • 13,797
  • 1
  • 42
  • 71
  • 7
    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. – Joris Timmermans Dec 03 '08 at 14:00
  • Who reads RTL? Surely none of my customers :-) *I think we don't need RTL support, do we?* – dom0 Jul 27 '13 at 19:14
  • This is an old post so probably my comment-qustion will not be answered : How to create a const pointer to a const pointer to a const MyStructure? – tchronis Jan 31 '15 at 15:22
  • 1
    @tchronis, I haven't tested (only that it compiles), but try something like: MyStructure const * const * const ptrMyStr; – Javier Mr Apr 28 '15 at 07:01
65

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
  • 15,148
  • 4
  • 32
  • 57
  • 1
    Very useful. Why isn't this tool well-known? – David Holm Dec 03 '08 at 10:59
  • Do you happen to know if it's available for windows? – Niklas Dec 03 '08 at 11:03
  • 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 Dec 03 '08 at 11:13
  • @flolo you are a hero! I have never heard of that tool! Thank you for sharing it! +1 – DJJ Mar 06 '20 at 03:01
  • Online version at [cdecl.org](http://cdecl.org) Works the other way round too! Enter the English, get the code. – Ant Jun 29 '20 at 10:21
24

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
  • 14,565
  • 6
  • 31
  • 36
  • What about MyStructure const* *ppMyStruct;? – tobi Jan 19 '13 at 20:56
  • 2
    @tobi, that's the same as the first line. See http://stackoverflow.com/q/3694630/ (they talk about references, but pointers behave the same). – efotinis Jan 20 '13 at 15:35
7

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
  • 10,937
  • 5
  • 57
  • 89
5

You are right.

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

Community
  • 1
  • 1
xtofl
  • 40,723
  • 12
  • 105
  • 192
3

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
  • 173,980
  • 10
  • 155
  • 350
  • 2
    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 Dec 09 '08 at 11:42
  • when i tried it i got this cdecl> explain struct MyStructure const** ppMyStruct; syntax error Can any one explain why if this is a right form C declaration – prajul May 22 '12 at 16:33
0
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
}