Topic: typedef, const, and pointers
Author: jak@cs.brown.edu (Jak Kirman)
Date: Tue, 9 Jun 1992 02:16:33 GMT Raw View
In article <1992Jun8.195529.7104@Warren.MENTORG.COM> adk@Warren.MENTORG.COM (Ajay Kamdar) writes:
> I have run into an extremely annoying and troublesome behavior that C++
> exhibits when const and typedef are used in conjunction with pointers.
> It makes life needlessly miserable.
>
> class Line;
> typedef Line* LinePtr;
> const LinePtr lp; // trouble spot
>
> All the AT&T Cfront based compilers I use interpret this as
> Line* const lp;
> rather than
> const Line* lp;
> as one would reasonably expect.
I have nothing to do with the standards committee, so I cannot speak for
them, but this seems to me to be exactly the correct behaviour.
const Line * lp;
declares a variable lp which is a pointer to a Line which is const.
That is, the Line is const. This says nothing about the pointer, and it
can be modified freely. You just can't modify what it points to.
const LinePtr lp;
says that lp is a LinePtr, and it is const. That is, the variable is a
pointer to a Line, and the variable is const. Now you are not allowed
to modify the pointer, but you may modify what it points to. This is
precisely the same as saying
Line * const lp;
i.e. lp is a constant pointer to a Line.
Declaring an object to be const and then having it not be const would be
very confusing --- what you suggest would allow the following:
const LinePtr lp;
lp = new Line;
Instead, the best solution would seem to be to make two typedefs for
these two types.
Jak Kirman jak@cs.brown.edu
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We know what happens to people who stay in the middle of the road.
They get run over.
-- Aneurin Bevan
Author: checker@acf3.nyu.edu (Christopher Hecker)
Date: 9 Jun 92 01:57:41 GMT Raw View
I probably shouldn't post this, but I can't help myself.
> class Line;
> typedef Line* LinePtr;
> const LinePtr lp; // trouble spot
>All the AT&T Cfront based compilers I use interpret this as
> Line* const lp;
>rather than
> const Line* lp;
>as one would reasonably expect.
You would only `reasonably expect' this if you insist on writing const
declarations/definitions differently than you read them. Now, the vast
majority of the world writes them the way you do, but I could never
figure this out. Here is what I am talking about:
int * p;
This obviously defines p to be a pointer to an int. When reading a
declaration/definition I read outward from the identifier. This allows
me to read arbitrarily complex declarations with relative ease. I
learned this technique from Greg Comeau's article in MSJ, and it has
never failed. Here's another example:
int * (* p)( void );
This makes p a pointer to a function returning a pointer to an int.
Duh, right? Notice how I read it. Now, using the same algorithm, read
this:
const int * p;
This defines p to be a pointer to an int const?!? That makes no sense
in english. Why not just write this:
int const * p;
This is (to me) ever so much clearer; p is a pointer to a const int.
How about this:
int const * const p;
p is a const pointer to a const int. When read, the const clearly
modifies in english what it modifies in code. If I had written it this
way:
const int * const p;
I would have p as a const pointer to an int const, and there is no
consistency to how the const reads; in other words, it reads differently
for each one in the definition. Why do people do this? Is there
something I'm missing? There seems to be no consistency to this style;
the first const comes before the type and the second comes after. Take
this:
int (* const p)( void );
p is a const pointer to an function returning int. If the language
allowed it, it would seem the the popular style would write it this way:
int (const * p)( void ); // error
which would read p is a pointer const to a function returning int.
Anyway, as I said, this is a style issue, but I can't see why people
choose to write their consts in an inconsistent way.
All of that said,
> class Line;
> typedef Line* LinePtr;
> const LinePtr lp; // trouble spot
>All the AT&T Cfront based compilers I use interpret this as
> Line* const lp;
>rather than
> const Line* lp;
>as one would reasonably expect.
If you wrote the consts the way I described above,
LinePtr const lp;
would clearly mean
Line * const lp;
In order to get this syntax
Line const * lp; (which is `const Line * lp' in your example)
you can see that you need to get your const `inbetween' the * and the
Line, which is impossible when the two have been typedef'ed together.
Now, before I get flamed from .nz to .ca, think. All I am saying is
that it seems to me that this
int const * const p;
is more consistent and readable than this
const int * const p;
because of the way declarations/definitions are read. Writing the
declarations like the former doesn't lead to tricky situations like the
post that I am replying to. If you think differently, fine. Explain to
me why the latter is more consistent (please, no replies like,
`everybody else does it that way').
Chris
Author: ark@alice.att.com (Andrew Koenig)
Date: 9 Jun 92 02:11:44 GMT Raw View
In article <1992Jun8.195529.7104@Warren.MENTORG.COM> adk@Warren.MENTORG.COM (Ajay Kamdar) writes:
> I have run into an extremely annoying and troublesome behavior that C++
> exhibits when const and typedef are used in conjunction with pointers.
> It makes life needlessly miserable.
> class Line;
> typedef Line* LinePtr;
> const LinePtr lp; // trouble spot
> All the AT&T Cfront based compilers I use interpret this as
> Line* const lp;
> rather than
> const Line* lp;
> as one would reasonably expect.
Correct.
> I have been informed that this interpretation is specified by ANSI C, and
> that the AT&T C++ compilers are doing the counterintuitive thing merely
> to be compatible with ANSI C.
You were informed correctly -- except that whether or not it's counter-
intuitive depends on your intuition.
> One doesn't need to stretch one's imagination too much to see how quickly
> things become ugly when the C++ compiler follows this interpretation.
If you still think so after you've read what follows, I would
appreciate it if you stretch my imagination a little.
Suppose that T represents some random type. You don't know what it is.
If I write
T* tp;
that declares tp as a pointer to an object of type T. If I write
const T* tq;
that declares tq as a pointer to an object of type const T. If I write
T* const tr = /* some value */;
that declares tr as a constant pointer to an object of type T, where
by `constant pointer' I mean one that is not allowed to change after
it has been initialized. For that reason I must initialize it. Finally,
const T* const ts = /* some value */;
declares ts as a constant pointer to an object of type const T.
Next, if I write
T t;
that declares t as an object of type T, and if I write
const T ct;
then that declares ct as an object of type const T.
I trust you will agree with me up to this point.
Now, suppose I say
typedef Line* T;
so that T is a name for the type `pointer to Line.' Then
T t;
declares t to be of type T, as we said before, and
const T ct;
declares ct to be of type `constant T,' again as we said before.
Now, if T is Line*, what does `constant T' mean? It means a Line*
object whose value is not allowed to change. In other words
const T ct;
Line* const ct;
declare ct to be the same type. It may be easier to see if I write it:
T const ct;
Line* const ct;
Are you still sure this is inappropriate behavior?
--
--Andrew Koenig
ark@europa.att.com
Author: eric@tfs.com (Eric Smith)
Date: Tue, 9 Jun 1992 05:58:14 GMT Raw View
In article <1992Jun9.015741.4299@cmcl2.nyu.edu> checker@acf3.nyu.edu (Christopher Hecker) writes:
...
>int const * const p;
>
>p is a const pointer to a const int. When read, the const clearly
>modifies in english what it modifies in code. If I had written it this
>way:
>
>const int * const p;
>
>I would have p as a const pointer to an int const, and there is no
>consistency to how the const reads; in other words, it reads differently
>for each one in the definition. Why do people do this? Is there
>something I'm missing? There seems to be no consistency to this style;
>the first const comes before the type and the second comes after. Take
"const int * const p" could be read as "const int pointed to by const p".
That allows a straightforward transliteration. Just translate "*" to
"pointed to by" (or whatever words best convey that meaning to you.)
After all, it's the "p" that's constant, not the "*" operator. The "*"
operator indicates that p is a pointer, and the const indicates that p
is constant, so together they indicate that p is a constant pointer, but
they both refer to p, not to each other.
The word "constant" is an adjective, so that sequence follows the
English convention of putting adjectives before nouns. I don't know
how widespread that convention is among other languages.
For the style you mention above as your preference, I'm not sure all
existing compilers will accept it, but it is perfectly legal as far
as I know.
Author: maxtal@extro.ucc.su.OZ.AU (John (MAX) Skaller)
Date: Tue, 9 Jun 1992 13:09:24 GMT Raw View
In article <1992Jun8.195529.7104@Warren.MENTORG.COM> adk@Warren.MENTORG.COM (Ajay Kamdar) writes:
>
>I have run into an extremely annoying and troublesome behavior that C++
>exhibits when const and typedef are used in conjunction with pointers.
>It makes life needlessly miserable.
>
> class Line;
> typedef Line* LinePtr;
> const LinePtr lp; // trouble spot
>
>All the AT&T Cfront based compilers I use interpret this as
> Line* const lp;
>rather than
> const Line* lp;
>as one would reasonably expect.
>
typedef should NOT work like a macro IMHO, it is used to
provide bindings in stages where the resulting C expression is
too messy to understand (and thats any expression with more than
1 pair of brackets ... or more than 3 symbols of any kind :-)
so I would expect that
const LinePtr lp
means
const [Line*] lp
that is, the Line* is a const, i.e.
Line* const lp
The fact that that seems conterintuitive (it is really awful!)
is not because typedef is wrong, but because C is plain awful
on types. Typedef is a way out of the mess. (Or use c++decl :-)
--
;----------------------------------------------------------------------
JOHN (MAX) SKALLER, maxtal@extro.ucc.su.oz.au
Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------
Author: Bruce.Hoult@bbs.actrix.gen.nz
Date: Wed, 10 Jun 1992 23:18:00 GMT Raw View
Chris Hecker writes:
>Now, before I get flamed from .nz to .ca
::flame on::
nah. On second thoughts, maybe not... :-)
::flame off::
--
Bruce.Hoult@bbs.actrix.gen.nz Twisted pair: +64 4 477 2116
BIX: brucehoult Last Resort: PO Box 4145 Wellington, NZ
"Cray's producing a 200 MIPS personal computer with 64MB RAM and a 1 GB
hard disk that fits in your pocket!" "Great! Is it PC compatable?"
Author: schrod@iti.informatik.th-darmstadt.de (Joachim Schrod)
Date: Thu, 11 Jun 1992 15:04:10 GMT Raw View
In article <1992Jun9.015741.4299@cmcl2.nyu.edu>, checker@acf3.nyu.edu (Christopher Hecker) writes:
> How about this:
>
> int const * const p;
>
> p is a const pointer to a const int. When read, the const clearly
> modifies in english what it modifies in code. If I had written it this
> way:
>
> const int * const p;
>
> I would have p as a const pointer to an int const, and there is no
> consistency to how the const reads; in other words, it reads differently
> for each one in the definition.
In the C course I just taught I told the students to read it as `p is
a constant pointer to an int, which is constant'.
--
Joachim
Author: garry@ithaca.com (Garry Wiegand)
Date: Fri, 12 Jun 92 10:19:38 GMT Raw View
In a recent article adk@Warren.MENTORG.COM (Ajay Kamdar) wrote:
>I have run into an extremely annoying and troublesome behavior that C++
>exhibits when const and typedef are used in conjunction with pointers.
>
> typedef Line* LinePtr;
> const LinePtr lp; // trouble spot
>
>All the AT&T Cfront based compilers I use interpret this as
> Line* const lp;
>rather than
> const Line* lp;
>as one would reasonably expect.
>...
>(on pg. 146) - "In effect, typedef is like #define, except that since it
>is interpreted by the compiler, .....". Strange behavior indeed for some
>thing which is supposed to be like #define.
No problem. The #define-equivalence rule of thumb just depends (in
this case) on using proper coding style: we just took a local vote
and agreed that it is a better style to always put the word "const"
AFTER the type name. For example, this:
float const * const foo;
"reads" better, right to left (love that C reverse Polish), than
const float * const foo;
They mean the same thing of course. Say each one to yourself, right
to left. (Note: "const float" does not count as one word! Nor
obviously does "const" count as a storage specifier all the way out
in front.)
Applying this improved coding style to your example,
> const LinePtr lp; // trouble spot
becomes
LinePtr const lp; // no trouble!
which presto chango indeed has the identical meaning to
Line* const lp;
You're welcome. The same reasoning applies to "volatile".
[I wonder why the C standards committee permitted both "float const"
and the unnecessary "const float".... probably was existing practice
at some important manufacturer. It just confuses people - I'm sure
there's lots of novices out there now who think the word "const" is
a storage specifier.]
Follow-up to the appropriate groups please, lang or std.
Garry Wiegand --- garry@ithaca.com --- Ithaca Software, Alameda, California
Author: adk@Warren.MENTORG.COM (Ajay Kamdar)
Date: Mon, 8 Jun 1992 19:55:29 GMT Raw View
I have run into an extremely annoying and troublesome behavior that C++
exhibits when const and typedef are used in conjunction with pointers.
It makes life needlessly miserable.
class Line;
typedef Line* LinePtr;
const LinePtr lp; // trouble spot
All the AT&T Cfront based compilers I use interpret this as
Line* const lp;
rather than
const Line* lp;
as one would reasonably expect.
I have been informed that this interpretation is specified by ANSI C, and
that the AT&T C++ compilers are doing the counterintuitive thing merely
to be compatible with ANSI C.
I unsuccessfully looked at the ARM and the the 2nd edition of K&R for some
light on this issue. I couldn't loacate any place where either of the books
explicitly addresses this specific case. In fact, K&R 2nd edition says
(on pg. 146) - "In effect, typedef is like #define, except that since it
is interpreted by the compiler, .....". Strange behavior indeed for some
thing which is supposed to be like #define.
One doesn't need to stretch one's imagination too much to see how quickly
things become ugly when the C++ compiler follows this interpretation.
Can someone on the C++ standards committee shed any further light on this
issue? Is this interpretation compliant with what the standards commitee
will eventually specify in the C++ standard? (I hope not.)
- Ajay
--
I speak for none but myself.
Ajay Kamdar Email : ajay_kamdar@mentorg.com
Mentor Graphics, IC Group (Warren, NJ) Phone : (908) 580-0102