multi-level pointer conversion with cv-qualifier, g++ doens't match Standard?

R

Road Tang

Greetings,

In standard, the multi-level pointer conversion whith cv-qualifiers is very
strict.

I wrote 3 converstion statement.
char t = 'a';
char **pp = &c;

char const **ppc = pp; //1. this is forbiden

BUT, for other 2 statment.
char const *const * pcpc = pp; //2
char const *const *const cpcpc = pp; //3

From clauses in C++Std 4.4 . I think the //2 is forbidden, and the //3 is
ok.
but after use g++ -ansi to compile, both //2 and //3 are passed.

So what happen?

Regards
-Road
 
R

Road Tang

Road said:
Greetings,

In standard, the multi-level pointer conversion whith cv-qualifiers is
very strict.

I wrote 3 converstion statement.
char t = 'a';
char **pp = &c;
correct, this is
char **p = &t;


and my g++ version
$ g++ --version
g++ (GCC) 4.2.3

I searched the c++-faq-lite , little words about the multi-level conversion.

Any clue?
 
I

Ivan Vecerina

: In standard, the multi-level pointer conversion whith cv-qualifiers is
very
: strict.
:
: I wrote 3 converstion statement.
: char t = 'a';
char *c = &t; // assumed here, for the rest of your code to work
: char **pp = &c;
:
: char const **ppc = pp; //1. this is forbiden
Forbidden indeed. The reason is that someone could now write:
const char const_char = 'a';
*ppc = &const_char;
** pp = 'X'; // oops ... overwriting const_char !!

: BUT, for other 2 statment.
: char const *const * pcpc = pp; //2
: char const *const *const cpcpc = pp; //3

Notice how the problem I illustrated above cannot
happen in these cases ?
So allowing them is the right thing to do...

If this is clear, note also that paragraph §4.4/4 in the standard
specifies the rule for conversion between pointer types.
It cannot refer to the constness of the variable in which the
result will be stored (so //2 and //3 are handled the same).


Terse topic ... but I hope this helps.
 
R

Road Tang

Ivan said:
: In standard, the multi-level pointer conversion whith cv-qualifiers is
very
: strict.
:
: I wrote 3 converstion statement.
: char t = 'a';
char *c = &t; // assumed here, for the rest of your code to work
: char **pp = &c;
:
: char const **ppc = pp; //1. this is forbiden
Forbidden indeed. The reason is that someone could now write:
const char const_char = 'a';
*ppc = &const_char;
** pp = 'X'; // oops ... overwriting const_char !!


: BUT, for other 2 statment.
: char const *const * pcpc = pp; //2
: char const *const *const cpcpc = pp; //3

Notice how the problem I illustrated above cannot
happen in these cases ?
So allowing them is the right thing to do...

Yeah, In these 2 cases, the pcpc and cpcpc have no oppotunity
to assigned to a const char. because of "middle" const qualifiers.
*pcpc = &const_char; // error, const type can't reassign
*cpcpc = &const_char; // error, const type can't reassign
So, //2 or //3 can pass theoretically.
If this is clear, note also that paragraph ¡ì4.4/4 in the standard
specifies the rule for conversion between pointer types.
It cannot refer to the constness of the variable in which the
result will be stored (so //2 and //3 are handled the same).

This is key problem i have, as i apprehend, the ¡ì4.4/4 forbids
statement //2, though the //2 doesn't have the risk of const-written.

char const *const * pcpc = pp; //2
for //2, as ¡ì4.4/4 like description

pp is "" pointer to "" pointer to "" char.
pcpc is "" pointer to "const" pointer to "const" char.

cv[1,j] are { "", "", "" }
cv[2,j] are { "", "const", "const"} (j = 0,1,2)

this doesn't match the ¡ì4.4/4 condition 3.
"-- if the cv[1,j] and cv[2,j] are different, then const is in every cv[2,k]
for 0<k<j"

consider j = 2, cv[1,j] != cv[2,j],
so if we can do conversion, should have "const" in cv[2,1]and cv[2,0].
the fact is cv[2,0] doesn't have const.

So this is the something surprising.
Terse topic ... but I hope this helps.
Oh, forgive my poor english, i'm not american guy,
but your impressive words help much.
 
R

Road Tang

gnuyuva said:
I don't know what you are asking exactly, but I am surprised by this
statement!!

oh, the right full statements are

char c = 'a';

// 1level
char *p = &c;
char const *p_c = p; // ok

// 2level
char **p_p = &p;
//char const ** p_p_c = p_p; // error
---> char const *const * p_cp_c = p_p; // ok
char const *const *const cp_cp_c = p_p; // ok

and my question is that why the marked line is OK in g++ , since standard
seems forbid the conversion.

sorry for my mistake.
 
I

Ivan Vecerina

: char const *const * pcpc = pp; //2
: for //2, as §4.4/4 like description
:
: pp is "" pointer to "" pointer to "" char.
: pcpc is "" pointer to "const" pointer to "const" char.
:
: cv[1,j] are { "", "", "" }
: cv[2,j] are { "", "const", "const"} (j = 0,1,2)
:
: this doesn't match the §4.4/4 condition 3.

You have to check the very beginning of §4.4/4:
"A conversion can add cv-qualifiers at levels
***other than the first***
in multi-level pointers, subject to the following rules:"

So the first level is excluded from the discussion that follows,
and all is well and makes sense ;-)

: > Terse topic ... but I hope this helps.
: Oh, forgive my poor english, i'm not american guy,
wo3 ye3 bu4 hi4 mei3guo2ren2 ! shi4 rui4shi4ren2.
(but I can only wish my Chinese was as good as your English)

Cheers,
Ivan
 
I

Ivan Vecerina

message : :: char const *const * pcpc = pp; //2
:: for //2, as §4.4/4 like description
::
:: pp is "" pointer to "" pointer to "" char.
:: pcpc is "" pointer to "const" pointer to "const" char.
::
:: cv[1,j] are { "", "", "" }
:: cv[2,j] are { "", "const", "const"} (j = 0,1,2)
::
:: this doesn't match the §4.4/4 condition 3.
:
: You have to check the very beginning of §4.4/4:
: "A conversion can add cv-qualifiers at levels
: ***other than the first***
: in multi-level pointers, subject to the following rules:"

I should have added that condition 3 specifies "for 0<k<j".
So the level where k==0 is excluded.

: So the first level is excluded from the discussion that follows,
: and all is well and makes sense ;-)
:
:: > Terse topic ... but I hope this helps.
:: Oh, forgive my poor english, i'm not american guy,
: wo3 ye3 bu4 hi4 mei3guo2ren2 ! shi4 rui4shi4ren2.
: (but I can only wish my Chinese was as good as your English)
:
: Cheers,
: Ivan
:
: --
: http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact
form
: Brainbench MVP for C++ <> http://www.brainbench.com
:
 
J

James Kanze

"Road Tang" <[email protected]> wrote in message
: char const *const * pcpc = pp; //2
: for //2, as §4.4/4 like description
: pp is "" pointer to "" pointer to "" char.
: pcpc is "" pointer to "const" pointer to "const" char.
: cv[1,j] are { "", "", "" }
: cv[2,j] are { "", "const", "const"} (j = 0,1,2)
: this doesn't match the §4.4/4 condition 3.
You have to check the very beginning of §4.4/4:
"A conversion can add cv-qualifiers at levels
***other than the first***
in multi-level pointers, subject to the following rules:"
So the first level is excluded from the discussion that follows,
and all is well and makes sense ;-)

Also, the result of a conversion is an rvalue, and rvalues of
pointer types don't have cv_qualifiers (or they are ignored).
There is absolutely no way for the results of a pointer
conversion to have the type:
char const * const* const
(This is, of course, *why* the top level const is excluded in
the discussion you cite.)
 
S

sods

message::: char const *const * pcpc = pp; //2
:: for //2, as §4.4/4 like description
::
:: pp is "" pointer to "" pointer to "" char.
:: pcpc is "" pointer to "const" pointer to "const" char.
::
:: cv[1,j] are { "", "", "" }
:: cv[2,j] are { "", "const", "const"} (j = 0,1,2)
::
:: this doesn't match the §4.4/4 condition 3.
:
: You have to check the very beginning of §4.4/4:
: "A conversion can add cv-qualifiers at levels
: ***other than the first***
: inmulti-level pointers, subject to the following rules:"

I should have added that condition 3 specifies "for 0<k<j".
So the level where k==0 is excluded.

: So the first level is excluded from the discussion that follows,
: and all is well and makes sense ;-)

Right, all is my careless.
I overleap the head, and just only stare at foot.
well, you make me find the head.

Thanks for perspicacious help.
:
:: > Terse topic ... but I hope this helps.
:: Oh, forgive my poor english, i'm not american guy,
: wo3 ye3 bu4 hi4 mei3guo2ren2 ! shi4 rui4shi4ren2.
: (but I can only wish my Chinese was as good as your English)
Wow~~, Switzerland, a beautiful place. your spell is also not
bad.
 
R

Road.Tang

: char const *const * pcpc = pp; //2
: for //2, as §4.4/4 like description
: pp is "" pointer to "" pointer to "" char.
: pcpc is "" pointer to "const" pointer to "const" char.
: cv[1,j] are { "", "", "" }
: cv[2,j] are { "", "const", "const"} (j = 0,1,2)
: this doesn't match the §4.4/4 condition 3.
You have to check the very beginning of §4.4/4:
"A conversion can add cv-qualifiers at levels
***other than the first***
inmulti-level pointers, subject to the following rules:"
So the first level is excluded from the discussion that follows,
and all is well and makes sense ;-)

Also, the result of a conversion is an rvalue, and rvalues of
pointer types don't have cv_qualifiers (or they are ignored).
There is absolutely no way for the results of a pointer
conversion to have the type:
char const * const* const
(This is, of course, *why* the top level const is excluded in
the discussion you cite.)

--
James Kanze (GABI Software) email:[email protected]
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

sods is me. ^_^
 
R

Road.Tang

: char const *const * pcpc = pp; //2
: for //2, as §4.4/4 like description
: pp is "" pointer to "" pointer to "" char.
: pcpc is "" pointer to "const" pointer to "const" char.
: cv[1,j] are { "", "", "" }
: cv[2,j] are { "", "const", "const"} (j = 0,1,2)
: this doesn't match the §4.4/4 condition 3.
You have to check the very beginning of §4.4/4:
"A conversion can add cv-qualifiers at levels
***other than the first***
inmulti-level pointers, subject to the following rules:"
So the first level is excluded from the discussion that follows,
and all is well and makes sense ;-)

Also, the result of a conversion is an rvalue, and rvalues of
pointer types don't have cv_qualifiers (or they are ignored).
There is absolutely no way for the results of a pointer
conversion to have the type:
char const * const* const
(This is, of course, *why* the top level const is excluded in
the discussion you cite.)

That's a good point.
so if ptr1 = ptr2, whatever type of ptr2 is,

when do lvalue-to-rvalue conversion, the top level const is gone.
so both T* -> T*, or T* -> T *const conversions are OK.

but i'm curious that why rvalue of pointer type can't have the cv-
qualifier ?
It seems the convention is from C, but i didn't found reasonable
explanation.
 
J

James Kanze

: char const *const * pcpc = pp; //2
: for //2, as §4.4/4 like description
: pp is "" pointer to "" pointer to "" char.
: pcpc is "" pointer to "const" pointer to "const" char.
: cv[1,j] are { "", "", "" }
: cv[2,j] are { "", "const", "const"} (j = 0,1,2)
: this doesn't match the §4.4/4 condition 3.
You have to check the very beginning of §4.4/4:
"A conversion can add cv-qualifiers at levels
***other than the first***
inmulti-level pointers, subject to the following rules:"
So the first level is excluded from the discussion that follows,
and all is well and makes sense ;-)
Also, the result of a conversion is an rvalue, and rvalues of
pointer types don't have cv_qualifiers (or they are ignored).
There is absolutely no way for the results of a pointer
conversion to have the type:
char const * const* const
(This is, of course, *why* the top level const is excluded in
the discussion you cite.)
That's a good point.
so if ptr1 = ptr2, whatever type of ptr2 is,
when do lvalue-to-rvalue conversion, the top level const is gone.
so both T* -> T*, or T* -> T *const conversions are OK.

More or less. I'm not sure what the exact wording in the
C++ standard says: whether there isn't any cv qualification, or
whether it is simply ignored in all cases. But it certainly
isn't used.
but i'm curious that why rvalue of pointer type can't have
the cv- qualifier ? It seems the convention is from C, but i
didn't found reasonable explanation.

It goes back to C, and what it means to be an rvalue in C. In
C, an rvalue is not an object, only a value. Since the
cv-qualifiers concern how you access or what you can do with an
object, they are irrelevant. You can't take the address of an
rvalue---it doesn't have one, and you can't modify it in any
way, because there's no object to modify. C doesn't attempt to
answer the question of whether &5 has type int* or int const*
(i.e. whether the rvalue 5 had type int or int const); it simply
bans all operations which would make it relevant. (And note
that both in C and in C++, an integer literal has type int, and
not int const.)

In C++, the issue is made somewhat more complex by the presence
of user functions. If I have a temporary like "int(5)", then
there really isn't any object, which would have an address and
be present in memory. If I have a temporary like "MyClass(5)",
on the other hand, I can call member functions on it, and those
member functions have a this pointer, which points to an actual
object in memory. After a fair amount of discussion in the C++
committee, it was decided that C++ would behave exactly like C
for non-class types (which in turn means that the rules for
class types and non-class types are different).
 
R

Road.Tang

On 21 mar, 12:52, "Ivan Vecerina"
: char const *const * pcpc = pp; //2
: for //2, as §4.4/4 like description
: pp is "" pointer to "" pointer to "" char.
: pcpc is "" pointer to "const" pointer to "const" char.
: cv[1,j] are { "", "", "" }
: cv[2,j] are { "", "const", "const"} (j = 0,1,2)
: this doesn't match the §4.4/4 condition 3.
You have to check the very beginning of §4.4/4:
"A conversion can add cv-qualifiers at levels
***other than the first***
inmulti-level pointers, subject to the following rules:"
So the first level is excluded from the discussion that follows,
and all is well and makes sense ;-)
Also, the result of a conversion is an rvalue, and rvalues of
pointer types don't have cv_qualifiers (or they are ignored).
There is absolutely no way for the results of a pointer
conversion to have the type:
char const * const* const
(This is, of course, *why* the top level const is excluded in
the discussion you cite.)
That's a good point.
so if ptr1 = ptr2, whatever type of ptr2 is,
when do lvalue-to-rvalue conversion, the top level const is gone.
so both T* -> T*, or T* -> T *const conversions are OK.

More or less. I'm not sure what the exact wording in the
C++ standard says: whether there isn't any cv qualification, or
whether it is simply ignored in all cases. But it certainly
isn't used.
but i'm curious that why rvalue of pointer type can't have
the cv- qualifier ? It seems the convention is from C, but i
didn't found reasonable explanation.

It goes back to C, and what it means to be an rvalue in C. In
C, an rvalue is not an object, only a value. Since the
cv-qualifiers concern how you access or what you can do with an
object, they are irrelevant. You can't take the address of an
rvalue---it doesn't have one, and you can't modify it in any
way, because there's no object to modify. C doesn't attempt to
answer the question of whether &5 has type int* or int const*
(i.e. whether the rvalue 5 had type int or int const); it simply
bans all operations which would make it relevant. (And note
that both in C and in C++, an integer literal has type int, and
not int const.)

Oh, So it is.

In C++, the issue is made somewhat more complex by the presence
of user functions. If I have a temporary like "int(5)", then
there really isn't any object, which would have an address and
be present in memory. If I have a temporary like "MyClass(5)",
on the other hand, I can call member functions on it, and those
member functions have a this pointer, which points to an actual
object in memory. After a fair amount of discussion in the C++
committee, it was decided that C++ would behave exactly like C
for non-class types (which in turn means that the rules for
class types and non-class types are different).

got it.
So, this is a design tradeoff problem..
C++ preserve the back-compatibility of plain old type.
You learn new feature, if you use class. or you live in your world.
that make sense.

Thanks for the incisive comment.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top