Topic: Pointer to array" -> "pointer to const array", Legal?
Author: rfg@netcom.com (Ronald F. Guilmette)
Date: Fri, 20 May 1994 08:23:50 GMT Raw View
In article <1994May19.130038.648@nlm.nih.gov> bkline%occs.nlm.nih.gov (Bob Kline) writes:
>Ronald F. Guilmette (rfg@netcom.com) wrote:
>: In article <1994May16.155159.24066@nlm.nih.gov> bkline%occs.nlm.nih.gov (Bob Kline) writes:
>: >
>: >That's quite a mouthful! I can understand why Dr. Stroustrup has little
>: >patience with the language lawyers. :->}
>
>: Oh yes. You're so right. It's so much easier on small minds to have
>: just a vague, ambiguous, and terse language description which each
>: implementor interprets differently. God forbid that we should have to
>: understand the languages we program in in any serious level of detail.
>: (Ouch. It gives me a headache just thinking about it.)
>
>: Oh yea... and to heck with all of the portability stuff. As long as we
>: stick with one compiler on MS-DOS we'll all be happy as clams... right?
>
>: --
>
>: -- Ron Guilmette, Sunnyvale, CA ---------- RG Consulting -------------------
>: ---- domain addr: rfg@netcom.com ----------- Purveyors of Compiler Test ----
>: ---- uucp addr: ...!uunet!netcom!rfg ------- Suites and Bullet-Proof Shoes -
>
>You can lighten up a little on the sarcasm. I recommend investing
>in a little book on the market entitled "Smileys" -- it will provide
>some insight into when the poster of an article is serious and when
>s/he isn't. If you look back at my earlier articles posted to this
>thread, you'll notice that I was the one urging that the original
>language in the ARM be provided with additional clarification. In
>fact, it may be that the language in the WP needs even further
>refinement, as at least one vendor is interpreting the existing
>language prohibiting implicit conversion of 'char **' to 'const char **'
>to apply equally to conversions of 'char (*)[n]' to 'const char (*)[n]'.
>
>:->}
My apologies to you and all readers of this newsgroup. I confess that
I didn't ``get'' your smilley.
In general however, some folks in the C++ community *have* denegrated the
experience, education, and hard work of the so-called `language lawyers'...
especially when they try to make things more precise... and that just makes
me see red. I guarrantee that anytime you want to get a response from me,
just start bad-mouthing `those darn persnickety language lawyers'.
--
-- Ron Guilmette, Sunnyvale, CA ---------- RG Consulting -------------------
---- domain addr: rfg@netcom.com ----------- Purveyors of Compiler Test ----
---- uucp addr: ...!uunet!netcom!rfg ------- Suites and Bullet-Proof Shoes -
Author: bkline%occs.nlm.nih.gov (Bob Kline)
Date: Mon, 23 May 94 01:36:42 GMT Raw View
[ in response to a suggestion that 'char const * ...' be preferred
to 'const char * ...']
Mark Christian Barnes (Aurelius@cup.portal.com) wrote:
: Agreed! And may I further recommend that the C++ language only
: accept the suggested form, as that is how const (and volatile ...)
: are bound during parsing.
Without arguing the merits of either side of the case (other than
to point out that in English modifiers generally precede their
substantives) it seems likely that the suggestion quoted above
will break most existing C++ source code. Most of the predominant
texts on the language (including Dr. Stroustrup's own publications)
use the form 'const char * ....'
--
/*----------------------------------------------------------------------*/
/* Bob Kline CSI Technologies */
/* bkline@smtp.csof.com Corporate Software, Inc. */
/* voice: (703) 522-0820 fax: (703) 522-5407 */
/*----------------------------------------------------------------------*/
Author: bkline%occs.nlm.nih.gov (Bob Kline)
Date: Tue, 24 May 94 12:55:18 GMT Raw View
I wrote:
: [ in response to a suggestion that 'char const * ...' be preferred
: to 'const char * ...']
: Mark Christian Barnes (Aurelius@cup.portal.com) wrote:
: : Agreed! And may I further recommend that the C++ language only
: : accept the suggested form, as that is how const (and volatile ...)
: : are bound during parsing.
: Without arguing the merits of either side of the case (other than
: to point out that in English modifiers generally precede their
: substantives) it seems likely that the suggestion quoted above
: will break most existing C++ source code. Most of the predominant
: texts on the language (including Dr. Stroustrup's own publications)
: use the form 'const char * ....'
Oops! I see I inadvertantly typed "... will break most existing C++
source code." I meant _would_ break .... I don't for a moment
believe that such a proposal would ever actually be adopted.
/*----------------------------------------------------------------------*/
/* Bob Kline CSI Technologies */
/* bkline@smtp.csof.com Corporate Software, Inc. */
/* voice: (703) 522-0820 fax: (703) 522-5407 */
/*----------------------------------------------------------------------*/
Author: pete@genghis.interbase.borland.com (Pete Becker)
Date: Tue, 17 May 1994 15:02:05 GMT Raw View
In article <CpsLqu.GDG@ucc.su.oz.au>,
John Max Skaller <maxtal@physics.su.OZ.AU> wrote:
>
> GAK! :-)
>
> I recommend people write:
>
> int const *
>
>and NOT
>
> const int *
>
>In general:
>
> int const * const * const * const
>
>is easier for me to understand that the equivalent:
>
> const int * const * const * const
>
I'll take that to heart. The next time I'm writing code for you I'll
try to use your conventions. In the meantime, I'll continue to write code in
a way that easy for me to understand.
-- Pete
Author: daniels@biles.com (Brad Daniels)
Date: Tue, 17 May 1994 15:58:56 GMT Raw View
In article <1994May17.003908.9375@nlm.nih.gov>,
Bob Kline <bkline%occs.nlm.nih.gov> wrote:
>Brad Daniels (daniels@biles.com) wrote:
...
>: void foo(char const **p)
>: {
>: *p = "hello world!";
>: }
>
>: int a() {
>: char *p;
>: foo(&p); // p will now point to the above string constant.
>: p[0] = 'x'; // Woops! trashed the constant!
>: }
>
>: In effect, allowing the T ** -> T const ** promotion allows you to
>: eliminate constness without any cast operations. This is not generally
>: considered a good thing, hence the requirement that intervening pointer
>: levels be const as well.
>
>Yes, you're quite right! Excellent explanation. I'm not sure it
>applies to the original poster's example, though, which involved
>a pointer to an array of 10 int's (given the fact that an array is,
>by definition, immutable on both sides of the fence).
Well, trying to pass a pointer to an array of integers is an int ** is
not going to work regardless of constness issues. From an internal
representational standpoint, (and according to the effects of the standard
C rules), a pointer to an array is the same as a straight pointer. Really,
it would kind of make sense to allow a pointer to an array degenerate to
a pointer to an object, though I don't think that's explicitly allowed
anywhere.
For example, given int (*c)[10], (*c)[1] means dereference c, convert it
to the address of an array [10] of int (yielding in effect (int *)c), then
add one to the resulting pointer and dereference the result. If you had
int **c, however, (*c)[1] would treat (*c) as returning a pointer, to which
would be added sizeof(int), and the value at the resulting address would be
evalutated as an integer if you didn't get access violation first.
- Brad
------------------------------------------------------------------------
+ Brad Daniels | "Let others praise ancient times; +
+ Biles and Associates | I am glad I was born in these." +
+ These are my views, not B&A's | - Ovid (43 B.C. - 17 A.D.) +
------------------------------------------------------------------------
Author: daniels@biles.com (Brad Daniels)
Date: Tue, 17 May 1994 16:30:36 GMT Raw View
In article <CpyF28.2Jt@biles.com>, Brad Daniels <daniels@biles.com> wrote:
>In article <1994May17.003908.9375@nlm.nih.gov>,
>Bob Kline <bkline%occs.nlm.nih.gov> wrote:
...
>>Yes, you're quite right! Excellent explanation. I'm not sure it
>>applies to the original poster's example, though, which involved
>>a pointer to an array of 10 int's (given the fact that an array is,
>>by definition, immutable on both sides of the fence).
>
>Well, trying to pass a pointer to an array of integers is an int ** is
>not going to work regardless of constness issues. ...
[ pointless discussion of mine deleted ]
I just traced back to the original article and realized that they were
in fact trying to pass it as T const (*)[], which of course implies the
requisite intervening constness, as you said. That's the problem with
long threads. You forget the details of where they started. I would
cancel the article, but I can't convince my newsreader I'm really me.
- Brad
--------------------------------------------------------------------------
+ Brad Daniels | I won't argue epistemology with you +
+ Biles and Associates | until you can prove unequivocally that +
+ These are my views, not B&A's | you are arguing epistemology with me. +
--------------------------------------------------------------------------
Author: rfg@netcom.com (Ronald F. Guilmette)
Date: Thu, 19 May 1994 09:13:22 GMT Raw View
In article <1994May16.155159.24066@nlm.nih.gov> bkline%occs.nlm.nih.gov (Bob Kline) writes:
>
>That's quite a mouthful! I can understand why Dr. Stroustrup has little
>patience with the language lawyers. :->}
Oh yes. You're so right. It's so much easier on small minds to have
just a vague, ambiguous, and terse language description which each
implementor interprets differently. God forbid that we should have to
understand the languages we program in in any serious level of detail.
(Ouch. It gives me a headache just thinking about it.)
Oh yea... and to heck with all of the portability stuff. As long as we
stick with one compiler on MS-DOS we'll all be happy as clams... right?
--
-- Ron Guilmette, Sunnyvale, CA ---------- RG Consulting -------------------
---- domain addr: rfg@netcom.com ----------- Purveyors of Compiler Test ----
---- uucp addr: ...!uunet!netcom!rfg ------- Suites and Bullet-Proof Shoes -
Author: bkline%occs.nlm.nih.gov (Bob Kline)
Date: Thu, 19 May 94 13:00:38 GMT Raw View
Ronald F. Guilmette (rfg@netcom.com) wrote:
: In article <1994May16.155159.24066@nlm.nih.gov> bkline%occs.nlm.nih.gov (Bob Kline) writes:
: >
: >That's quite a mouthful! I can understand why Dr. Stroustrup has little
: >patience with the language lawyers. :->}
: Oh yes. You're so right. It's so much easier on small minds to have
: just a vague, ambiguous, and terse language description which each
: implementor interprets differently. God forbid that we should have to
: understand the languages we program in in any serious level of detail.
: (Ouch. It gives me a headache just thinking about it.)
: Oh yea... and to heck with all of the portability stuff. As long as we
: stick with one compiler on MS-DOS we'll all be happy as clams... right?
: --
: -- Ron Guilmette, Sunnyvale, CA ---------- RG Consulting -------------------
: ---- domain addr: rfg@netcom.com ----------- Purveyors of Compiler Test ----
: ---- uucp addr: ...!uunet!netcom!rfg ------- Suites and Bullet-Proof Shoes -
You can lighten up a little on the sarcasm. I recommend investing
in a little book on the market entitled "Smileys" -- it will provide
some insight into when the poster of an article is serious and when
s/he isn't. If you look back at my earlier articles posted to this
thread, you'll notice that I was the one urging that the original
language in the ARM be provided with additional clarification. In
fact, it may be that the language in the WP needs even further
refinement, as at least one vendor is interpreting the existing
language prohibiting implicit conversion of 'char **' to 'const char **'
to apply equally to conversions of 'char (*)[n]' to 'const char (*)[n]'.
:->}
--
/*----------------------------------------------------------------------*/
/* Bob Kline CSI Technologies */
/* bkline@smtp.csof.com Corporate Software, Inc. */
/* voice: (703) 522-0820 fax: (703) 522-5407 */
/*----------------------------------------------------------------------*/
Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Wed, 18 May 1994 14:00:04 GMT Raw View
In article <1994May16.155159.24066@nlm.nih.gov> bkline%occs.nlm.nih.gov (Bob Kline) writes:
>Jason Merrill (jason@cygnus.com) wrote:
>
>: - Two pointer types and T2 are similar if there exists a type T and |
>: integer N>0 such that: |
>
>: T1 is Tcv1,n * . . . cv1,1 * cv1,0
>
>: and |
>
>: T2 is Tcv2,n * . . . cv2,1 * cv2,0
>
>That's quite a mouthful! I can understand why Dr. Stroustrup has little
>patience with the language lawyers. :->}
>
>I'll be eager to read the justification when (if?) my copy of the WP
>ever shows up. The more I think about the original poster's question,
>the less sense it makes to disallow T ** -> T const **.
The justification is simple. The conversions should be allowed
because they are safe.
--
JOHN (MAX) SKALLER, INTERNET:maxtal@suphys.physics.su.oz.au
Maxtal Pty Ltd, CSERVE:10236.1703
6 MacKay St ASHFIELD, Mem: SA IT/9/22,SC22/WG21
NSW 2131, AUSTRALIA
Author: bkline%occs.nlm.nih.gov (Bob Kline)
Date: Fri, 20 May 94 11:46:09 GMT Raw View
Ronald F. Guilmette (rfg@netcom.com) wrote:
: My apologies to you and all readers of this newsgroup. I confess that
: I didn't ``get'' your smilley.
No problem. I'm not a language lawyer myself, but I appreciate the
hard work that has to go into the making of a standard that does its
job properly.
/*----------------------------------------------------------------------*/
/* Bob Kline CSI Technologies */
/* bkline@smtp.csof.com Corporate Software, Inc. */
/* voice: (703) 522-0820 fax: (703) 522-5407 */
/*----------------------------------------------------------------------*/
Author: Aurelius@cup.portal.com (Mark Christian Barnes)
Date: Sat, 21 May 94 23:45:54 PDT Raw View
John Skaller writes:
> GAK! :-)
>
> I recommend people write:
>
> int const *
>
>and NOT
>
> const int *
>
>In general:
>
> int const * const * const * const
>
>is easier for me to understand that the equivalent:
>
> const int * const * const * const
>
Agreed! And may I further recommend that the C++ language only
accept the suggested form, as that is how const (and volatile ...)
are bound during parsing.
The freedom place certain language keywords in arbitrary order
doesn't seem too important to me. It's only a source of confusion
and errors to beginners and sloows down the compilation process.
Other than allowing programmers to argue over the stylistic
merits of:
volatile int * const kpvInt;
int volatile * const kpvInt;
and incouraging white space idioms like:
const char *const kpkChar;
to remind one that you're abusing the proper binding.
What's the point?
Regards, Aurelius@cup.portal.com
Author: jason@cygnus.com (Jason Merrill)
Date: Mon, 16 May 1994 09:53:41 GMT Raw View
Here is the pertinent section from the latest WP. Notice that while T** ->
T *const * and T** -> T const *const * are standard pointer conversions,
T** -> T const ** is not.
Jason
- Two pointer types and T2 are similar if there exists a type T and |
integer N>0 such that: |
T1 is Tcv1,n * . . . cv1,1 * cv1,0
and |
T2 is Tcv2,n * . . . cv2,1 * cv2,0
where each cvi,j is const, volatile, const volatile, or |
nothing. An expression of type T1 may be converted to type T2 if |
and only if the following conditions are satisfied: |
- the pointer types are similar. |
- for every j>0, if const is in cv1,j then const is in cv2,j, |
and similarly for volatile. |
- the cv1,j and cv2,j are different, then const is in every cv2,k |
for 0<k<j. |
Author: bkline%occs.nlm.nih.gov (Bob Kline)
Date: Sun, 15 May 94 18:54:11 GMT Raw View
Pete Becker (pete@genghis.interbase.borland.com) wrote:
: Let's simplify a bit. It doesn't affect the answer, but it avoids some
: confusion. Instead of a pointer to an array, think about a pointer to a
: pointer:
: void f( const int** );
: int **ip;
: f(ip);
: This call is illegal. The rule about converting a T* to a const T* is not
: talking about text substitution. It is talking about types. If we treat
: the declaration int **ip as creating a T*, then 'T' must be int*. Which means
: that the trivial conversion applies to (int *), that is, to the pointer. So
: int ** can be converted to int *const *, a pointer to a const pointer to int.
: That is not the same thing as a const int **, which is a pointer to a pointer
: to a const int.
: -- Pete
While I agree that the call is illegal -- if we can assume that the list
of "trivial conversions" in the ARM is exclusive (and we would of course
be on more solid ground here if there was an explicit statement to that
effect in the text) -- it seems difficult to explain the reasoning for
rejecting this call when (as with the conversion of T* to const T*) the
only difference between the actual and formal arguments boils down to a
higher level of protection against mutability than the caller requires.
It becomes even more difficult to explain in the face of the assertion
two pages later that, other than breaking ties, constness does not affect
argument matching. I guess I'm less convinced than you that this question
would not benefit from additional clarifying language in the forthcoming
standard. Judging from the results of the survey of existing implementa-
tions, I'd say I'm not alone! :->}
--
/*----------------------------------------------------------------------*/
/* Bob Kline CSI Technologies */
/* bkline@smtp.csof.com Corporate Software, Inc. */
/* voice: (703) 522-0820 fax: (703) 522-5407 */
/*----------------------------------------------------------------------*/
Author: bkline%occs.nlm.nih.gov (Bob Kline)
Date: Mon, 16 May 94 15:51:59 GMT Raw View
Jason Merrill (jason@cygnus.com) wrote:
: Here is the pertinent section from the latest WP. Notice that while T** ->
: T *const * and T** -> T const *const * are standard pointer conversions,
: T** -> T const ** is not.
: Jason
: - Two pointer types and T2 are similar if there exists a type T and |
: integer N>0 such that: |
: T1 is Tcv1,n * . . . cv1,1 * cv1,0
: and |
: T2 is Tcv2,n * . . . cv2,1 * cv2,0
: where each cvi,j is const, volatile, const volatile, or |
: nothing. An expression of type T1 may be converted to type T2 if |
: and only if the following conditions are satisfied: |
: - the pointer types are similar. |
: - for every j>0, if const is in cv1,j then const is in cv2,j, |
: and similarly for volatile. |
: - the cv1,j and cv2,j are different, then const is in every cv2,k |
: for 0<k<j. |
That's quite a mouthful! I can understand why Dr. Stroustrup has little
patience with the language lawyers. :->}
I'll be eager to read the justification when (if?) my copy of the WP
ever shows up. The more I think about the original poster's question,
the less sense it makes to disallow T ** -> T const **.
/*----------------------------------------------------------------------*/
/* Bob Kline CSI Technologies */
/* bkline@smtp.csof.com Corporate Software, Inc. */
/* voice: (703) 522-0820 fax: (703) 522-5407 */
/*----------------------------------------------------------------------*/
Author: mecklen@oops.cs.utah.edu (Robert Mecklenburg)
Date: 16 May 1994 18:36:34 GMT Raw View
Pete Becker (pete@genghis.interbase.borland.com) wrote:
>>Robert Mecklenburg (mecklen@oops.cs.utah.edu) wrote:
>>: typedef int T;
>>: void foo( const T (*)[1] );
>>: void bar() {
>>: T (*a)[1];
>>: foo( a );
>>: }
>>
>>: The question is: "Is the call of foo correct?" We believe that it is.
>
> Let's simplify a bit. It doesn't affect the answer, but it avoids some
>confusion. Instead of a pointer to an array, think about a pointer to a
>pointer:
>
> void f( const int** );
> int **ip;
> f(ip);
I believe this is the real question and may be the source of the
compiler error:
Is "int **ip" equivalent to "int (*ia)[1]"?
If so, then I agree that the call is illegal. I believe they are not.
Let's draw some pictures:
int **ip;
ip: +----+ +----+ +----+
| o------>| ip'----->| 10 |
+----+ +----+ +----+
int (*ia)[1];
ia: +----+ +----+
| o------>| 10 |
+----+ +----+
Given these two pictures the rationale for the "T ** => T * const *"
rule (of which I was already aware) is clear. You would not want the
"ip'" pointer rerouted to an immutable integer.
However, it is also clear that "ia" should not decay to "int **", but
rather to "int * const *" since the base address of an array is
constant -- there is no word in memory whose value you could change.
>So
>int ** can be converted to int *const *, a pointer to a const pointer to int.
>That is not the same thing as a const int **, which is a pointer to a pointer
>to a const int.
Agreed. And that is the source of the compiler error with "ia" and
"a" above.
****** Apparently, the compiler is incorrectly ******
****** converting "int (*)[1]" to "int **". ******
So, Pete, your intent was to simplify the example, but you wound up
changing the semantics. We can now see that the original query with
"a" and "foo" is more equivalent to:
void f( const int * const * );
int * const * ip;
f( ip );
Which _is_ safe, and I believe, legal.
In fact, this code compiles on IBM's C++ (which fails in the original
example), AT&T 3.0.1, and G++ 2.5.8. It does not compile on DEC's
C++, where it generates the error:
y.C:3: error: In this statement, the referenced type of the
pointer value "ip" is "const pointer to signed int", which is
not compatible with "const pointer to const signed int".
Which is a nonsensical error message.
So, the original question has not been answered:
******* Is the call of foo correct? ********
Thanks,
Robert Mecklenburg
Russ Fish
University of Utah
Author: daniels@biles.com (Brad Daniels)
Date: Mon, 16 May 1994 20:21:08 GMT Raw View
In article <1994May16.155159.24066@nlm.nih.gov>,
Bob Kline <bkline%occs.nlm.nih.gov> wrote:
...
>I'll be eager to read the justification when (if?) my copy of the WP
>ever shows up. The more I think about the original poster's question,
>the less sense it makes to disallow T ** -> T const **.
It's because of a nasty little problem shown in this example.
void foo(char const **p)
{
*p = "hello world!";
}
int a() {
char *p;
foo(&p); // p will now point to the above string constant.
p[0] = 'x'; // Woops! trashed the constant!
}
In effect, allowing the T ** -> T const ** promotion allows you to
eliminate constness without any cast operations. This is not generally
considered a good thing, hence the requirement that intervening pointer
levels be const as well.
- Brad
------------------------------------------------------------------
+ Brad Daniels | How do you spell "zilophone?" +
+ Biles and Associates | How many right answers are +
+ These are my views, not B&A's | to that question? +
------------------------------------------------------------------
Author: bkline%occs.nlm.nih.gov (Bob Kline)
Date: Tue, 17 May 94 00:39:08 GMT Raw View
Brad Daniels (daniels@biles.com) wrote:
: In article <1994May16.155159.24066@nlm.nih.gov>,
: Bob Kline <bkline%occs.nlm.nih.gov> wrote:
: ...
: >I'll be eager to read the justification when (if?) my copy of the WP
: >ever shows up. The more I think about the original poster's question,
: >the less sense it makes to disallow T ** -> T const **.
: It's because of a nasty little problem shown in this example.
: void foo(char const **p)
: {
: *p = "hello world!";
: }
: int a() {
: char *p;
: foo(&p); // p will now point to the above string constant.
: p[0] = 'x'; // Woops! trashed the constant!
: }
: In effect, allowing the T ** -> T const ** promotion allows you to
: eliminate constness without any cast operations. This is not generally
: considered a good thing, hence the requirement that intervening pointer
: levels be const as well.
: - Brad
: ------------------------------------------------------------------
: + Brad Daniels | How do you spell "zilophone?" +
: + Biles and Associates | How many right answers are +
: + These are my views, not B&A's | to that question? +
: ------------------------------------------------------------------
Yes, you're quite right! Excellent explanation. I'm not sure it
applies to the original poster's example, though, which involved
a pointer to an array of 10 int's (given the fact that an array is,
by definition, immutable on both sides of the fence).
--
/*----------------------------------------------------------------------*/
/* Bob Kline CSI Technologies */
/* bkline@smtp.csof.com Corporate Software, Inc. */
/* voice: (703) 522-0820 fax: (703) 522-5407 */
/*----------------------------------------------------------------------*/
Author: jason@cygnus.com (Jason Merrill)
Date: Tue, 17 May 1994 02:26:30 GMT Raw View
>>>>> Robert Mecklenburg <mecklen@oops.cs.utah.edu> writes:
> However, it is also clear that "ia" should not decay to "int **", but
> rather to "int * const *" since the base address of an array is
> constant -- there is no word in memory whose value you could change.
I disagree. I think it is clear that "ia" should not decay to anything,
but should remain "int (*)[1]". Pointers to arrays (and references to
arrays) do not decay. Incrementing a pointer to an array of 5 ints is very
different from incrementing a pointer to a const pointer to int.
> So, the original question has not been answered:
> ******* Is the call of foo correct? ********
I believe that it is. Unfortunately, the current WP says nothing about
conversions from one array type to another. Cfront seems to allow just
about any array conversion, while xlC allows just about none. I imagine
that a safe rule of thumb would be the one you outlined in your article,
i.e. replacing all instances of "array of" in the type with "const pointer
to" and checking whether that pointer conversion is allowed. This does not
cover conversions between arrays with different bounds; my inclination is
to disallow such conversions.
Jason
Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Sat, 14 May 1994 11:54:58 GMT Raw View
In article <1994May13.164757.26170@nlm.nih.gov> bkline%occs.nlm.nih.gov (Bob Kline) writes:
>in the ARM (if it hasn't already). The ARM, on p. 318, lists the
>"trivial conversions" which are performed when matching calls to
>functions. A conversion of T* to const T* is included in this list.
FYI: The Working Paper no longer contains any notion
of trivial conversions. Instead, there are bindings:
T --> T const&
is a binding of a const ref to an rvalue (mediated by the allocation
and initialisation of a temporary).
And, the conversion T*-->T const* has always been
a Standard Conversion, not trivial. See Ch4 "Standard Conversions",
4.6 "Pointer Conversions".
--
JOHN (MAX) SKALLER, INTERNET:maxtal@suphys.physics.su.oz.au
Maxtal Pty Ltd, CSERVE:10236.1703
6 MacKay St ASHFIELD, Mem: SA IT/9/22,SC22/WG21
NSW 2131, AUSTRALIA
Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Sat, 14 May 1994 12:37:41 GMT Raw View
In article <Cpro05.L89@borland.com> pete@genghis.interbase.borland.com (Pete Becker) writes:
>
> Let's simplify a bit. It doesn't affect the answer, but it avoids some
>confusion. Instead of a pointer to an array, think about a pointer to a
>pointer:
>
> void f( const int** );
> int **ip;
> f(ip);
>
>This call is illegal. The rule about converting a T* to a const T* is not
>talking about text substitution. It is talking about types. If we treat
>the declaration int **ip as creating a T*, then 'T' must be int*. Which means
>that the trivial conversion applies to (int *), that is, to the pointer. So
>int ** can be converted to int *const *, a pointer to a const pointer to int.
>That is not the same thing as a const int **, which is a pointer to a pointer
>to a const int.
GAK! :-)
I recommend people write:
int const *
and NOT
const int *
In general:
int const * const * const * const
is easier for me to understand that the equivalent:
const int * const * const * const
--
JOHN (MAX) SKALLER, INTERNET:maxtal@suphys.physics.su.oz.au
Maxtal Pty Ltd, CSERVE:10236.1703
6 MacKay St ASHFIELD, Mem: SA IT/9/22,SC22/WG21
NSW 2131, AUSTRALIA
Author: bkline%occs.nlm.nih.gov (Bob Kline)
Date: Fri, 13 May 94 16:47:57 GMT Raw View
Robert Mecklenburg (mecklen@oops.cs.utah.edu) wrote:
: We have a question on the correct use of const. Given the following
: code fragment:
: typedef int T;
: void foo( const T (*)[1] );
: void bar() {
: T (*a)[1];
: foo( a );
: }
: The question is: "Is the call of foo correct?" We believe that it is.
: Our logic is as follows:
You pose a good question, and I suspect your answer will be correct
once the standards committee has added some refinement to the language
in the ARM (if it hasn't already). The ARM, on p. 318, lists the
"trivial conversions" which are performed when matching calls to
functions. A conversion of T* to const T* is included in this list.
If you use this list as your criterion, then legally the compilers
which reject your call of foo() seem to have the stronger case, since
your pointers are not pointers to T (const or otherwise), but to arrays
of T (not the same thing, as the sizeof operator will tell you). On
the other hand, if you take the sentence two pages later ("In other words,
"constness" acts as a tie-breaker where needed but does not affect
argument matching otherwise") without the context of the preceding
language or of the table of trivial conversions, then it would seem
that the call should be accepted. Common sense would also argue in
favor of accepting the call, but some of your reasoning seems to stray
a little:
: 1. The local variable 'a' is a "pointer to an array of mutable Ts".
True
: 2. The call of foo must convert this into a "pointer to an array of
: immutable Ts".
Also true.
: 3. This should be safe since the called function cannot change the
: value of the actual argument, only the formal argument.
Not relevant. It is true that the called function will only change
a copy of the argument, but the argument is the pointer, not the
data to which const protection is being applied. The real reason
this is safe is that the called function is guaranteeing that it will
not change the data in the array, which is more than the original
declaration of 'a' asked for.
: 4. Since changing a "pointer to array of immutable Ts" from one array
: to another is safe, this conversion should be safe.
There's only one array, not two. It's the pointer which is being copied
for the called function, not the array being pointed to.
BTW, I tried your example with two more compilers. One (Borland) accepts
the function call, and the other (Microsoft) rejects it.
/*----------------------------------------------------------------------*/
/* Bob Kline CSI Technologies */
/* bkline@smtp.csof.com Corporate Software, Inc. */
/* voice: (703) 522-0820 fax: (703) 522-5407 */
/*----------------------------------------------------------------------*/
Author: pete@genghis.interbase.borland.com (Pete Becker)
Date: Sat, 14 May 1994 00:28:53 GMT Raw View
In article <1994May13.164757.26170@nlm.nih.gov>,
Bob Kline <bkline%occs.nlm.nih.gov> wrote:
>Robert Mecklenburg (mecklen@oops.cs.utah.edu) wrote:
>: We have a question on the correct use of const. Given the following
>: code fragment:
>
>: typedef int T;
>: void foo( const T (*)[1] );
>: void bar() {
>: T (*a)[1];
>: foo( a );
>: }
>
>: The question is: "Is the call of foo correct?" We believe that it is.
>: Our logic is as follows:
>
>
>You pose a good question, and I suspect your answer will be correct
>once the standards committee has added some refinement to the language
>in the ARM (if it hasn't already). The ARM, on p. 318, lists the
>"trivial conversions" which are performed when matching calls to
>functions. A conversion of T* to const T* is included in this list.
>If you use this list as your criterion, then legally the compilers
>which reject your call of foo() seem to have the stronger case, since
>your pointers are not pointers to T (const or otherwise), but to arrays
>of T (not the same thing, as the sizeof operator will tell you).
Let's simplify a bit. It doesn't affect the answer, but it avoids some
confusion. Instead of a pointer to an array, think about a pointer to a
pointer:
void f( const int** );
int **ip;
f(ip);
This call is illegal. The rule about converting a T* to a const T* is not
talking about text substitution. It is talking about types. If we treat
the declaration int **ip as creating a T*, then 'T' must be int*. Which means
that the trivial conversion applies to (int *), that is, to the pointer. So
int ** can be converted to int *const *, a pointer to a const pointer to int.
That is not the same thing as a const int **, which is a pointer to a pointer
to a const int.
-- Pete
Author: mecklen@oops.cs.utah.edu (Robert Mecklenburg)
Date: 11 May 1994 21:55:18 GMT Raw View
We have a question on the correct use of const. Given the following
code fragment:
typedef int T;
void foo( const T (*)[1] );
void bar() {
T (*a)[1];
foo( a );
}
The question is: "Is the call of foo correct?" We believe that it is.
Our logic is as follows:
1. The local variable 'a' is a "pointer to an array of mutable Ts".
2. The call of foo must convert this into a "pointer to an array of
immutable Ts".
3. This should be safe since the called function cannot change the
value of the actual argument, only the formal argument.
4. Since changing a "pointer to array of immutable Ts" from one array
to another is safe, this conversion should be safe.
We have two compilers which claim this conversion is an error:
DEC cxx:
% cxx -c x.C
x.C:5: error: In this statement, the referenced type of
the pointer value "a" is "array [1] of signed int",
which is not compatible with "array [1] of const
signed int".
Compilation terminated with errors.
IBM xlC:
% xlC -c x.C
"x.C", line 5.1: 1540-055: (S) "T(*)[1]" cannot be
converted to "const T(*)[1]".
"x.C", line 5.1: 1540-306: (I) The previous message
applies to argument 1 of function "foo(const
T(*)[1])".
And three compilers which accept it:
G++ 2.5.8
HP B2402 A.02.34
AT&T 3.0.1
Sun 2.0 (based on AT&T 3.0.1)
SGI (based on AT&T 3.0.1)
Can someone tells us the correct answer.
Thanks,
Robert Mecklenburg
Russ Fish
University of Utah