Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Pointer to array of array of const pointer

Reply
Thread Tools

Pointer to array of array of const pointer

 
 
RSL
Guest
Posts: n/a
 
      02-18-2010
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.


 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      02-18-2010
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
 
Reply With Quote
 
 
 
 
RSL
Guest
Posts: n/a
 
      02-18-2010
On Feb 18, 10:28*am, Victor Bazarov <(E-Mail Removed)> 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);
}

 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      02-18-2010
RSL wrote:
> On Feb 18, 10:28 am, Victor Bazarov <(E-Mail Removed)> 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
 
Reply With Quote
 
Gert-Jan de Vos
Guest
Posts: n/a
 
      02-18-2010
On Feb 18, 3:47*pm, RSL <(E-Mail Removed)> 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.
 
Reply With Quote
 
RSL
Guest
Posts: n/a
 
      02-18-2010
On Feb 18, 1:32 pm, Victor Bazarov <(E-Mail Removed)> 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.

 
Reply With Quote
 
RSL
Guest
Posts: n/a
 
      02-18-2010
On Feb 18, 2:05*pm, Gert-Jan de Vos <gert-
(E-Mail Removed)> wrote:
> On Feb 18, 3:47*pm, RSL <(E-Mail Removed)> 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.


 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      02-19-2010
RSL wrote:
> On Feb 18, 1:32 pm, Victor Bazarov <(E-Mail Removed)> 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
 
Reply With Quote
 
RSL
Guest
Posts: n/a
 
      02-19-2010
On Feb 18, 8:14*pm, Victor Bazarov <(E-Mail Removed)> 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.

 
Reply With Quote
 
RSL
Guest
Posts: n/a
 
      02-19-2010
On Feb 18, 8:14*pm, Victor Bazarov <(E-Mail Removed)> 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.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
const pointer versus const content pointed to by pointer Disc Magnet C Programming 1 05-06-2010 10:27 AM
const vector<A> vs vector<const A> vs const vector<const A> Javier C++ 2 09-04-2007 08:46 PM
Casting int'** to 'const int * const * const' dosn't work, why? Jonas.Holmsten@gmail.com C Programming 11 07-01-2007 06:16 PM
Smart Pointer release() const : it can set the pointer to null with the keyword "const"? coala C++ 1 09-06-2006 03:00 PM
Smart Pointer release() const : it can set the pointer to null with the keyword "const"? coala C++ 3 09-06-2006 02:58 PM



Advertisments