Archived

This topic is now archived and is closed to further replies.

I didn't know this after 14 years of C/C++

This topic is 6522 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

I''ve been programming C/C++ for 14 years (I used it for a year before they taught a class at the university) and I just learned something I didn''t know. I''ve tried this in MS Visual C/C++ 6.0 and Borland C/C++ 5.0 with the same result (better error message in VC btw). If anyone having a pure C compiler tries this, could let me know what happens, please. This problem started while working on a template class for doubly linked lists (i''m entertaining myself), but its the class definition not the template that is the problem. Here is the problem using only classes: Originally I wrote something like this, class Node { Node* prev, next; } which gets gets a compile-time error. In VC it says something about ''next'' and the fact that ''Node'' is being defined. A slight change to the above - class Node { Node* prev; Node* next; } gets no compile-time error. What surprised me was that I thought these were equivalent. They are for if you replace ''Node*'' in the class body with ''int*'' and both versions compile or substitute an already defined structure for ''Node''. I guess there is some syntactical rule having to do with self referential data structures that makes the first version illegal, but I haven''t found any documentation to explain or note this fact. If anyone can turn me on to something about this let me know. Thanks, Mike Roberts aka milo mlbobs@telocity.com

Share on other sites
I think that if you would declare them like this:
Node *next,*prev;

It should work

If you code it, they will come...

Commander M
http://commanderm.8m.com
cmndrm@commanderm.8m.com

Share on other sites
small mistake i think.
class Node
{
Node* prev, next;
}

is eq to
class Node
{
Node* prev;
Node next;
}

Note that there is no * in front of next...

-kertropp

C:\Projects\rg_clue\ph_opt.c(185) : error C3142: 'PushAll' :bad idea
C:\Projects\rg_clue\ph_opt.c(207) : error C324: 'TryCnt': missing point

Share on other sites
Duh!
Dang!

Somehow I had convinced myself that my first C++ book (C++ for C Programmers by Ira Pohl) that I got in 1990 said there was a change in pointer declaration syntax (it doesn''t). I though the change resulted in the fact that the line ''int* p, q;'' created two integer pointers and that ''int *p, q'' would be one integer pointer and one integer.

I guess I got confused because I had always used the form ''int *p, *q'' and in Pohl''s book he uses two lines, ''int *p;'' and ''int *q''. For some reason this screwed with my mojo and I thought that ''int* p, q'' would do the job. )

Funny thing is that at work (pure C stuff) I still use ''int *p'' to stay in style with some older code (older code of mine) and at home I must have never needed to declare two pointers at home where I had adopted ''int* p;''. So when I needed two pointers I just did ''int* p, q'' which is dead wrong.

About two minutes after reading Kertropp''s post (thanks for the pointing out the obvious Kertropp! ) I found in my newer C++ book (2nd Edition C++ Primer Plus by Stephen Prata)on page 121 a very specific warning to not do what I did. Dang nabbit and sufferin succotash! And to think I was one those C programmers who, due to earlier assembly programming experience, pretty quickly (and fully) understood pointers.

The real irony I guess is that I bought Pohl''s book because I learned C from a book he wrote with Al Kelley called ''A Book on C'' that I loved so much, as was so complete, that I never needed another. I''ve never even needed the ''must have book'' by Kerningham and Ritchie. And then ole Ira screws with mind!

Michael L. Roberts
aka milo
mlbobs@telocity.com

Share on other sites
I had a problem like this and never new why it worked when I changed it to two lines of code. Thanks for clearing that up

Share on other sites
nothing to be ashamed of, this happened to me just one week ago.
(but i didn''t post it up the board.. )

Share on other sites
man, that is annoying! I ran into the same problem a while ago when making my own linked list class.

Doesn''t it seem more logical that
Blah * prev, next;
*should* be the same as
blah * prev,
* next;

or whatever... I guess that''s why there is usually a data type, then an LP data type in most code.
ie
BYTE a, b;

just so you don''t have to put that damn asterisk! =)
LPBYTE a, b;

Share on other sites
One thing I always make a point of doing is to attach the notation to the variable, not the type.

Rather than
String * pString;

I have
String *pString;

Just makes it a bit more obvious to me. Some books seem to do the opposite, putting the adornment on the type, which is downright confusing.

Share on other sites
quote:
Original post by johnhattan

One thing I always make a point of doing is to attach the notation to the variable, not the type.

Rather than
String * pString;

I have
String *pString;

Just makes it a bit more obvious to me. Some books seem to do the opposite, putting the adornment on the type, which is downright confusing.

Well, your way makes it more difficult to make a mistake in declaring pointers, which is good. But the other way (String* pString ) is equally valid as it follows the syntax of any other (ie. non-pointer) definition, which is type on the left (in this case, pointer to string), name on the right (pString). Personally I prefer this way, as my variable is of type String*. It just means I have to declare everything on separate lines to be clear.

Share on other sites
My C++ book suggests the asterisk near the variable, but it''s a personal decision. I still make that error sometimes myself *sigh*

#pragma DWIM // Do What I Mean!
**I use Software Mode**

Share on other sites
Whatever you do, never declare two variables on the same line.

- null_pointer
Sabre Multimedia

Share on other sites
Looks like you guys forgot about operator precedence! A pointers ''*'' comes way before a comma. That''s why it evaluates the first as a pointer to NODE, but not the second. Maybe ( NODE * ) next, prev; would work ( though it would make for some ugly code... )? I agree with null_pointer, one line per declaration is a good practice It may look innocent declaring more than one variable on a line, but if you get in that habit, it can hurt readability bad.

Dan Arson

Share on other sites
Operator precedence doesn''t enter into it. This is declaration syntax, which is an entirely different part of the grammar from expression evaluation. The language (C in this case) was explicitly designed this way so that declarations of variables would mirror their later usage. Thus, just as you write:

*foo

To get the contents of a pointer named foo, you also write:

*foo

To declare a pointer named foo. I''m not saying this is a GOOD thing, as it is the cause of more than a few errors in every programmer''s lifetime. Nonetheless, this is one of the reasons that I''ve fallen into the mode of always putting optional specifiers (like pointer, array, etc...) with the variable name. Which leaves me with a question:

For people that place the ''*'' after the type, rather than before the variable... What do you do with array brackets? Worse, how about arrays of pointers? Just wondering.

-Brian

Share on other sites
Double post

I agree that MOST of the time one declaration per line is alright, but imagine doing that with code like this:

int maxXI, maxYI, maxZI, minXI, minYI, minZI;

No pointers there, so no confusion. Wouldn''t do it with pointers, unless I wanted to get a yell from across the room saying something like "HEY, that code you checked in causes a GPF!"

#pragma DWIM // Do What I Mean!
**I use Software Mode**

Share on other sites
quote:
Original post by osmanb

For people that place the '*' after the type, rather than before the variable... What do you do with array brackets? Worse, how about arrays of pointers? Just wondering.

This makes sense to me:
SomeClass* array[400];

There is nothing to the right of the array brackets to consider binding it to, so there's no complication, as far as I can see? The above is an array of pointers to SomeClass - to put the asterisk on the right would seem to imply (to me) that (a) We are using SomeClass objects, which we are not, and (b) That we are dereferencing 'array', which we are not (at this stage).

Consider: I may wish to typedef my pointers thus:

typedef SomeObject* SomeObjectPtr;

So now, these 2 statements are equivalent:

SomeObject* a_pointer;
SomeObjectPtr a_pointer;

I can now declare an array of pointers just like I could declare an array of any other type:

SomeObjectPtr a_pointer_array[100];

No reason why I should have asterisks hanging around just because the contents of the array happen to be pointer-like.
This enforces my 'belief' that the asterisk is part of the type rather than the variable. Your milage may vary.

Edited by - Kylotan on 4/17/00 11:16:00 AM

Share on other sites
Oh, my gawd! I''ve started a reasonable discussion.

Just for the record, I don''t declare multiple variables on one line for readability. Nor do I wish to type the same type name over and over. I use the following format.

int x,
y,
z;

Much neater than either,

int x, y, z;

or,

int x;
int y;
int z;

in my opinion.

Like I said in an earlier post I somehow convinced myself that the C++ syntax interpreted ''int*'' differently from ''int *''.

I concur that it is somewhat clearer to think of it as I am declaring integer pointers (int*) instead of I''m declaring a pointer to an integer (int *). Too bad the syntax doesn''t actually do that though.

And for the record, I''ll be using this format ''int *x'' from now on. Just like I used to.

Mike Roberts
aka milo
mlbobs@telocity.com

Share on other sites
quote:
Original post by null_pointer

Whatever you do, never declare two variables on the same line.

- null_pointer
Sabre Multimedia

I dunno about the above. I declare more than one variable per line at times when it's best organized (pointers always receive a new line though).

int x, y, z, max_x, max_y, max_z;for pointers=int * px, * py;
the type def is the way to go though

Edited by - iwasbiggs on 4/17/00 5:29:36 PM

Share on other sites
Sorry if this has already been mentioned, but you might want to look at a book by Scott Meyers "Effective C++". It contains a lot of those kinds of things you wish other books mentioned, in the form of a bunch of (50) tips chapters. VEry highly recommended...