Pointer to array of array of const pointer

Discussion in 'C++' started by RSL, Feb 18, 2010.

  1. RSL

    RSL Guest

    In order to let compiler catches unintended changes of a passed object
    in a function, we added const, for example:

    struct MyStruct
    {
    int Value;
    };

    void bar(const MyStruct * const pObj)
    {
    // pObj = <address of another MyStruct object>;
    // pObj->Value = <some value>;
    }

    int main()
    {
    MyStruct AObj;

    bar(&AObj);
    }

    If uncommented the two lines in bar(), the compiler should be able to
    catch them.

    This also works for array of (const) pointers (to const):

    void foo(MyStruct const *const (PtrAry)[10])
    {
    // PtrAry[0] = <address of another MyStruct object>;
    // PtrAry[0]->Value = <some value>;
    }

    int main()
    {
    MyStruct *AryOfPtr[10] = { &AObj };
    // ...
    foo(AryOfPtr);
    }

    However, it does not works for array-of-array:

    void foobar(MyStruct* const (*PtrAry)[10])
    {
    // PtrAry[0][0] = <address of another MyStruct object>;
    PtrAry[0][0]->Value = 20;
    }

    int main()
    {
    MyStruct *ary2[10][10];
    // ...
    foobar(ary2);
    }

    In foobar(),
    PtrAry[0][0]->Value = 20;
    is allowed. This is expected because MyStruct is not declared as
    const.

    However, if foobar() is declared as such:
    void foobar(const MyStruct* const (*PtrAry)[10])
    {
    // PtrAry[0][0] = <address of another MyStruct object>;
    // PtrAry[0][0]->Value = <some value>;
    }

    Compiler can catch both lines (if uncommented) but generate an error
    in main (cannot convert parameter 1 from 'MyStruct *[10][10]' to
    'const MyStruct *const (*)[10]')

    Is it possible to declare foobar() such that PtrAry points to an
    arrays of pointer to non-modifiable object.
    RSL, Feb 18, 2010
    #1
    1. Advertising

  2. RSL wrote:
    > [..]
    > However, if foobar() is declared as such:
    > void foobar(const MyStruct* const (*PtrAry)[10])
    > {
    > // PtrAry[0][0] = <address of another MyStruct object>;
    > // PtrAry[0][0]->Value = <some value>;
    > }
    >
    > Compiler can catch both lines (if uncommented) but generate an error
    > in main (cannot convert parameter 1 from 'MyStruct *[10][10]' to
    > 'const MyStruct *const (*)[10]')
    >
    > Is it possible to declare foobar() such that PtrAry points to an
    > arrays of pointer to non-modifiable object.


    So, to make PtrAry a pointer, you put * in front.
    To make it point to an array, you surround it with parens and put the
    brackets to the right.
    Each element of the array is declared of the type that is to the left of
    the parens. You want it (an element) to be a pointer, put the star in
    front of it. The type goes to the left of that.

    In the order explained:

    *PtrAry : a pointer


    (*PtrAry)[] : a pointer to an array


    *(*PtrAry)[] : a pointer to an array of pointers

    MyStruct const *(*PtrAry)[] :
    a pointer to an array of pointers to const MyStruct objects

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Feb 18, 2010
    #2
    1. Advertising

  3. RSL

    RSL Guest

    On Feb 18, 10:28 am, Victor Bazarov <> wrote:
    > So, to make PtrAry a pointer, you put * in front.
    > To make it point to an array, you surround it with parens and put the
    > brackets to the right.
    > Each element of the array is declared of the type that is to the left of
    > the parens.  You want it (an element) to be a pointer, put the star in
    > front of it.  The type goes to the left of that.
    >
    > In the order explained:
    >
    >                *PtrAry      :       a pointer
    >
    >                (*PtrAry)[]  :      a pointer to an array
    >
    >               *(*PtrAry)[]  :   a pointer to an array of pointers
    >
    > MyStruct const *(*PtrAry)[]  :
    >          a pointer to an array of pointers to const MyStruct objects
    >


    Right, but then, I am not able to call the function, and pass a non-
    const argument:
    int main()
    {
    MyStruct *ary2[10][10];
    // ...
    foobar(ary2);
    }

    What I want is to maintain const-correctness from within the
    function. The function promise not to modify the pointer PtrAry[n]
    [m], and the object PtrAry[n][m] points to. Therefore, the compiler
    should be able to flag the following lines as error:
    PtrAry[0][0] = ...; /* [1] */
    PtrAry[0][0]->Value = ...; /* [2] */

    In order for the compiler to catch [1], the function needs to be
    declared as:
    void foobar(MyStruct *const (*PtrAry)[10] )

    In order for the compielr to catch [2], another 'const' needs to be
    added before the leftmost '*':
    void foobar(const MyStruct *const (*PtrAry)[10] )


    OTOH, single dimensional array works as expected:
    struct MyStruct
    {
    int Value;
    };

    // Pointer to const array of const pointer
    void foo(MyStruct const *const (PtrAry)[10])
    {
    //PtrAry[0] = ...;
    //PtrAry[0]->Value = ...;
    }
    int main()
    {
    MyStruct *AryOfPtr[10];
    foo(AryOfPtr);
    }
    RSL, Feb 18, 2010
    #3
  4. RSL wrote:
    > On Feb 18, 10:28 am, Victor Bazarov <> wrote:
    >> So, to make PtrAry a pointer, you put * in front.
    >> To make it point to an array, you surround it with parens and put the
    >> brackets to the right.
    >> Each element of the array is declared of the type that is to the left of
    >> the parens. You want it (an element) to be a pointer, put the star in
    >> front of it. The type goes to the left of that.
    >>
    >> In the order explained:
    >>
    >> *PtrAry : a pointer
    >>
    >> (*PtrAry)[] : a pointer to an array
    >>
    >> *(*PtrAry)[] : a pointer to an array of pointers
    >>
    >> MyStruct const *(*PtrAry)[] :
    >> a pointer to an array of pointers to const MyStruct objects
    >>

    >
    > Right, but then, I am not able to call the function, and pass a non-
    > const argument:
    > int main()
    > {
    > MyStruct *ary2[10][10];
    > // ...
    > foobar(ary2);
    > }


    I think this is explained in the C FAQ. Hmm... Where is it?... Hold
    on, I'll find it for you... Ah, here it is: http://c-faq.com/. See
    question 6.18. Or, another explanation is given in C++ FAQ 18.17.

    > What I want is to maintain const-correctness from within the
    > function. The function promise not to modify the pointer PtrAry[n]
    > [m], and the object PtrAry[n][m] points to. Therefore, the compiler
    > should be able to flag the following lines as error:
    > PtrAry[0][0] = ...; /* [1] */
    > PtrAry[0][0]->Value = ...; /* [2] */
    >
    > In order for the compiler to catch [1], the function needs to be
    > declared as:
    > void foobar(MyStruct *const (*PtrAry)[10] )


    That's a [single] pointer to an array of ten constant pointers.

    > In order for the compielr to catch [2], another 'const' needs to be
    > added before the leftmost '*':
    > void foobar(const MyStruct *const (*PtrAry)[10] )


    Yes.

    I think you already said that before.

    > OTOH, single dimensional array works as expected:


    (Why OTOH?)

    > struct MyStruct
    > {
    > int Value;
    > };
    >
    > // Pointer to const array of const pointer
    > void foo(MyStruct const *const (PtrAry)[10])


    That's not a pointer to a const array. It's simply a pointer. The fact
    that you write '10' between the brackets does not really matter. This
    is one of the old (and not necessarily all that great) features of the
    language, a carryover from C. According to the rules of declarations,
    your function is actually:

    void foo(MyStruct const* const* PtrAry)

    (meaning, 'PtrAry' is a pointer to a const pointer to a const MyStruct).

    > {
    > //PtrAry[0] = ...;
    > //PtrAry[0]->Value = ...;
    > }
    > int main()
    > {
    > MyStruct *AryOfPtr[10];
    > foo(AryOfPtr);
    > }
    >


    Yes, that's OK. Since the type of the expression 'AnyOfPtr' (yes, it's
    an expression) is 'MyStruct**', it is convertible to 'MyStruct const*
    const*'. That's how the language works.

    I am still trying to grok what problem you're trying to solve.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Feb 18, 2010
    #4
  5. On Feb 18, 3:47 pm, RSL <> wrote:
    > ...
    > However, if foobar() is declared as such:
    >     void foobar(const MyStruct* const (*PtrAry)[10])
    >     {
    >         // PtrAry[0][0] = <address of another MyStruct object>;
    >         // PtrAry[0][0]->Value = <some value>;
    >     }
    >
    > Compiler can catch both lines (if uncommented) but generate an error
    > in main (cannot convert parameter 1 from 'MyStruct *[10][10]' to
    > 'const MyStruct *const (*)[10]')
    >
    > Is it possible to declare foobar() such that PtrAry points to an
    > arrays of pointer to non-modifiable object.


    No. 4.4 Qualification conversions details the const/volatile
    conversions. These conversions are supported on multi level
    pointers but not in arrays. So there is no conversion from an
    array of MyStruct* to an array of const MyStruct*, or vice
    versa. Why it works with 1D arrays is because the top level
    array declaration in a function parameter is interpreted as a
    pointer, there the qualification conversions are supported.
    Gert-Jan de Vos, Feb 18, 2010
    #5
  6. RSL

    RSL Guest

    On Feb 18, 1:32 pm, Victor Bazarov <> wrote:
    > I am still trying to grok what problem you're trying to solve.


    Thanks for the explanation.

    Forget about the one-dimensional example, I think I've messed up. Let
    me start over again...

    What I want to know is as follow:

    Given the codes:
    struct MyStruct
    {
    int Value;
    };

    int main()
    {
    MyStruct* AryPtr[10][10];
    foo(AryPtr);
    }

    and the following properties for foo():
    - It will not modify AryPtr[n][m].
    - It will not modify AryPtr[n][m]->Value.

    How should foo() be declared for the compiler to enforce the
    properties?

    In other word, if I accidentally write these in foo(), ('AryPtr' is
    the formal argument in foo()):
    AryPtr[0][0] = <something>;
    AryPtr[0][0]->Value = <some value>;

    I want the compiler to catch and report errors.
    RSL, Feb 18, 2010
    #6
  7. RSL

    RSL Guest

    On Feb 18, 2:05 pm, Gert-Jan de Vos <gert-
    > wrote:
    > On Feb 18, 3:47 pm, RSL <> wrote:
    >
    > > ...
    > > However, if foobar() is declared as such:
    > >     void foobar(const MyStruct* const (*PtrAry)[10])
    > >     {
    > >         // PtrAry[0][0] = <address of another MyStruct object>;
    > >         // PtrAry[0][0]->Value = <some value>;
    > >     }

    >
    > > Compiler can catch both lines (if uncommented) but generate an error
    > > in main (cannot convert parameter 1 from 'MyStruct *[10][10]' to
    > > 'const MyStruct *const (*)[10]')

    >
    > > Is it possible to declare foobar() such that PtrAry points to an
    > > arrays of pointer to non-modifiable object.

    >
    > No. 4.4 Qualification conversions details the const/volatile
    > conversions. These conversions are supported on multi level
    > pointers but not in arrays. So there is no conversion from an
    > array of MyStruct* to an array of const MyStruct*, or vice
    > versa. Why it works with 1D arrays is because the top level
    > array declaration in a function parameter is interpreted as a
    > pointer, there the qualification conversions are supported.


    Okay, I just read this after I send the last reply to Victor. I guess
    it cannot be done if using multidimensional array.

    Thanks.
    RSL, Feb 18, 2010
    #7
  8. RSL wrote:
    > On Feb 18, 1:32 pm, Victor Bazarov <> wrote:
    >> I am still trying to grok what problem you're trying to solve.

    >
    > Thanks for the explanation.
    >
    > Forget about the one-dimensional example, I think I've messed up. Let
    > me start over again...
    >
    > What I want to know is as follow:
    >
    > Given the codes:
    > struct MyStruct
    > {
    > int Value;
    > };
    >
    > int main()
    > {
    > MyStruct* AryPtr[10][10];
    > foo(AryPtr);
    > }
    >
    > and the following properties for foo():
    > - It will not modify AryPtr[n][m].
    > - It will not modify AryPtr[n][m]->Value.
    >
    > How should foo() be declared for the compiler to enforce the
    > properties?
    >
    > In other word, if I accidentally write these in foo(), ('AryPtr' is
    > the formal argument in foo()):
    > AryPtr[0][0] = <something>;
    > AryPtr[0][0]->Value = <some value>;
    >
    > I want the compiler to catch and report errors.
    >


    So, the array has to be of const values and each value has to be a
    pointer to a const object. And you want to be able to use your
    two-dimensional array of pointers to non-const objects in that function.

    I see. Hmm... I don't think it's possible. It seems that you want
    something like

    struct A { int i; };
    A ga;

    void foo(A const* const myarr[][10])
    // 'myarr' is a pointer to an array of 10 const pointers to const A
    {
    myarr[5][5] = &ga; // gives an error
    myarr[5][5]->i = 42; // gives an error
    }

    int main()
    {
    A *pAarr[10][10];
    foo(pAarr);
    }

    But those deeply-seated 'const' qualifiers confuse the conversion
    mechanism, and do not allow this conversion to happen.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Feb 19, 2010
    #8
  9. RSL

    RSL Guest

    On Feb 18, 8:14 pm, Victor Bazarov <> wrote:
    >
    > So, the array has to be of const values and each value has to be a
    > pointer to a const object.  And you want to be able to use your
    > two-dimensional array of pointers to non-const objects in that function.
    >
    > I see.  Hmm...  I don't think it's possible.  It seems that you want
    > something like
    >
    >     struct A { int i; };
    >     A ga;
    >
    >     void foo(A const* const myarr[][10])
    > // 'myarr' is a pointer to an array of 10 const pointers to const A
    >     {
    >         myarr[5][5] = &ga; // gives an error
    >         myarr[5][5]->i = 42; // gives an error
    >     }
    >
    >     int main()
    >     {
    >         A *pAarr[10][10];
    >         foo(pAarr);
    >     }
    >
    > But those deeply-seated 'const' qualifiers confuse the conversion
    > mechanism, and do not allow this conversion to happen.


    Yes, after reading through all the reply and the Standard, I reckon it
    cannot be done this way.

    Thanks for all who helps.
    RSL, Feb 19, 2010
    #9
  10. RSL

    RSL Guest

    On Feb 18, 8:14 pm, Victor Bazarov <> wrote:
    >
    > So, the array has to be of const values and each value has to be a
    > pointer to a const object.  And you want to be able to use your
    > two-dimensional array of pointers to non-const objects in that function.
    >
    > I see.  Hmm...  I don't think it's possible.  It seems that you want
    > something like
    >
    >     struct A { int i; };
    >     A ga;
    >
    >     void foo(A const* const myarr[][10])
    > // 'myarr' is a pointer to an array of 10 const pointers to const A
    >     {
    >         myarr[5][5] = &ga; // gives an error
    >         myarr[5][5]->i = 42; // gives an error
    >     }
    >
    >     int main()
    >     {
    >         A *pAarr[10][10];
    >         foo(pAarr);
    >     }
    >
    > But those deeply-seated 'const' qualifiers confuse the conversion
    > mechanism, and do not allow this conversion to happen.


    Yes, after reading through all the reply and the Standard, I reckon it
    cannot be done this way.

    Thanks for all who helps.
    RSL, Feb 19, 2010
    #10
  11. RSL

    RSL Guest

    On Feb 18, 8:14 pm, Victor Bazarov <> wrote:
    >
    > So, the array has to be of const values and each value has to be a
    > pointer to a const object.  And you want to be able to use your
    > two-dimensional array of pointers to non-const objects in that function.
    >
    > I see.  Hmm...  I don't think it's possible.  It seems that you want
    > something like
    >
    >     struct A { int i; };
    >     A ga;
    >
    >     void foo(A const* const myarr[][10])
    > // 'myarr' is a pointer to an array of 10 const pointers to const A
    >     {
    >         myarr[5][5] = &ga; // gives an error
    >         myarr[5][5]->i = 42; // gives an error
    >     }
    >
    >     int main()
    >     {
    >         A *pAarr[10][10];
    >         foo(pAarr);
    >     }
    >
    > But those deeply-seated 'const' qualifiers confuse the conversion
    > mechanism, and do not allow this conversion to happen.


    Yes, after reading through all the reply and the Standard, I reckon it
    cannot be done this way.

    Thanks for all who helps.
    RSL, Feb 19, 2010
    #11
  12. RSL

    RSL Guest

    Oops, I accidentally refreshes the page twice and multiply the last
    reply. Is there any way to delete duplicated postings?

    Really sorry about this.
    RSL, Feb 19, 2010
    #12
  13. Victor Bazarov wrote:
    > RSL wrote:
    >> [..]
    >> However, if foobar() is declared as such:
    >> void foobar(const MyStruct* const (*PtrAry)[10])
    >> {
    >> // PtrAry[0][0] = <address of another MyStruct object>;
    >> // PtrAry[0][0]->Value = <some value>;
    >> }
    >>
    >> Compiler can catch both lines (if uncommented) but generate an error
    >> in main (cannot convert parameter 1 from 'MyStruct *[10][10]' to
    >> 'const MyStruct *const (*)[10]')
    >>
    >> Is it possible to declare foobar() such that PtrAry points to an
    >> arrays of pointer to non-modifiable object.

    >
    > So, to make PtrAry a pointer, you put * in front.
    > To make it point to an array, you surround it with parens and put the
    > brackets to the right.
    > Each element of the array is declared of the type that is to the left of
    > the parens. You want it (an element) to be a pointer, put the star in
    > front of it. The type goes to the left of that.
    >
    > In the order explained:
    >
    > *PtrAry : a pointer
    >
    >
    > (*PtrAry)[] : a pointer to an array
    >
    >
    > *(*PtrAry)[] : a pointer to an array of pointers
    >
    > MyStruct const *(*PtrAry)[] :
    > a pointer to an array of pointers to const MyStruct objects


    In other words : too complex, and if the OP can not decipher it on his
    own, he is going to create a maintenance nightmare.
    Vladimir Jovic, Feb 19, 2010
    #13
  14. RSL wrote:
    > Oops, I accidentally refreshes the page twice and multiply the last
    > reply. Is there any way to delete duplicated postings?
    >
    > Really sorry about this.


    Not after they have propagated. Usually you'd use the "cancel"
    functionality offered by your newsreader software. If you're using
    Google web interface (I don't), I have no idea if it has a way to do that.

    Don't worry about it.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Feb 19, 2010
    #14
  15. RSL

    RSL Guest

    On Feb 19, 7:11 am, Victor Bazarov <> wrote:
    > RSL wrote:
    > > Oops, I accidentally refreshes the page twice and multiply the last
    > > reply.  Is there any way to delete duplicated postings?

    >
    > > Really sorry about this.

    >
    > Not after they have propagated.  Usually you'd use the "cancel"
    > functionality offered by your newsreader software.  If you're using
    > Google web interface (I don't), I have no idea if it has a way to do that..


    I was using the Google web interface.

    After that, I explore a little and find that there is a clickable
    "More options" at the beginning of each reply. Click it, it will
    expand and show more clickable action links. One of them is
    "Remove".

    (One have to login first and can only remove own message).


    > Don't worry about it.


    Thanks.


    > V
    > --
    > Please remove capital 'A's when replying by e-mail
    > I do not respond to top-posted replies, please don't ask
    RSL, Feb 19, 2010
    #15
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. coala
    Replies:
    3
    Views:
    364
    coala
    Sep 6, 2006
  2. coala
    Replies:
    1
    Views:
    579
    Victor Bazarov
    Sep 6, 2006
  3. Replies:
    11
    Views:
    1,090
  4. Javier
    Replies:
    2
    Views:
    549
    James Kanze
    Sep 4, 2007
  5. Disc Magnet
    Replies:
    1
    Views:
    617
    Ian Collins
    May 6, 2010
Loading...

Share This Page