Declaration mimics use. "int * x" means that "*x" is an "int", not that "x" is an "int *". If it meant the latter, then "int* x,y" would declare two pointers. It's all in K&R, all in K&R; bless me, what do they teach them at these schools?
I had to double-check that C++ references worked the same way; since Stroustrup believes in the wrong notation for pointers, I had a nasty feeling he might have built the wrong semantics into his bit of the language. But no; "int&x,y" declares y to be an int, not a reference, so regardless of Stroustrup's own silly spacing convention the same rule applies for sane people.
I generally strive for int* x; with the self-imposed restriction that I don't have multiple variable declarations per line (which gets around the gotcha). I've no justification for this other than it is more pleasing for me. I would kill anyone who did int a, *b, c; because I, at least, would miss that one :).
More generally I like a 'minimal criminal' form of Hungarian notation where I slap a 'p' to the front for each layer of indirection when it is known (int* pX; int** ppX; etc.).
The part of this I have trouble with is reconciling "self-imposed restriction" with "would kill anyone who [violated it]". Either it's a principle everyone should adhere to, or it's a principle you personally choose to adhere to, but I don't think you can have it both ways. Surely?
I suppose it would work if you were operating in a closed community of C programmers who had all adopted the same coding style, but this is the real world and like everybody else you have to read code written in a wide variety of styles. Does it not therefore make sense to go with rather than against the intended usage of the language, so that code written in any style is just as legible to you?
My restriction is multiple declarations per-line. The example of kill-worthy actions is a subset of that where not only are there multiple declarations (which is a personal choice) but mixing pointer and non-pointer declarations which I think is really hard to notice and is prone to generating buggy code.
Does it not therefore make sense to go with rather than against the intended usage of the language, so that code written in any style is just as legible to you?
Yes unless that usage is completely confusing. Doing
if(...)
foo();
bar();
is valid in the language but I'd never do that 'cos of the confusion it'd generate.
Good God, you're starting to put me off C for life here! What on earth is that supposed to be, a variable declaration? I'm sure Java does it in a more fluffy way. We loves the languages that hide low-level weirdness, we does. :P
Java doesn't have pointers and pretty much everything is a reference rather than a value type (except where it isn't[1]) so it neatly gets around the problem by not having to have a notation for it :).
Yes. While int x; declares x to be an int (i.e. an integer), int *x; declares x to be a pointer to an integer. Strictly, it declares that *x is an int. Is that clear? :)
FTR *y means "value pointed to by y", similarly &z means "address of z".
I prefer int* x; as it mimics the mental description I use - I read that as "int-pointer x". Correctness of C/C++ style is probably not very high on my list of Important Life Skills, it must be said... (nor, for that matter, is 'Ability to write C++')
Of course, if I sit and think about it, this means my mental model is slightly flawed - I still read * as 'pointer to' rather than 'dereference of' when I'm not paying attention, and thus lose the subleties.
And with that, I'm back to programming in Java. Have fun ^_^
I'd agree that most people who don't read K&R for fun or who don't really care if ANSI ruined/improved the language would read it as "int-pointer x". I certainly do.
Correctness of C/C++ style is probably not very high on my list of Important Life Skills
Correctness isn't but consistency within a project is. Generally coding styles are religious wars so it is probably best if one is at least aware of your own personal gotchas but try to avoid them if you ever have any wiggle room.
I do quite like perl, but I wouldn't have said it was better than C in terms of how putting punctuation symbols in the wrong places can create ambiguous code :)
I don't really mind. "*x is an integer" makes sense, but not when you start dealing with &s. "int* " would make sense if the language did it like that but it doesn't. Calling it something other than x would be most nice :)
Writing int *x; is a visual hint that the * binds more tightly to the x than it does to the int. If you write it this way by habit you're more likely to remember to write int *x, *y; when you want to declare two pointers rather than int* x, y; which declares a pointer and an integer.
C allows so many weird things that many things are really a matter of personal preference; like perl, there are many more or less good reasons on either side.
Declaring more than one variable per line is fine for simple types, but types should not be mixed, no matter how legal. "int a, *b, c;" is valid, but bad, as it declares two ints and a pointer in a single statement. Too much information in very little space is the lifeblood of the IOCCC, for a good reason. Multiple identical structs should for the same readability reason not be declared as "struct { ... } foo,bar;".
In C++, classes are essentially "complex types"; references should only ever be used to pass classes by value, as const references. Everything else has far too much potential for bugs, unreadability, and confusion. A const& has the advantage of not needing a copy constructor (often dangerous for complex classes, which may need to do all sorts of initialisation on construction, almost always pointless overhead) while preserving by-value semantics (being read-only but directly usable without requiring careful dereferencing).
So. I write "int main(int argc, char* argv[])" to make explicit that argv is an array of char*. I write "int* a;", or "int *a, *b;" if I really need more than once. I also prefer C++ in oh so many ways, but would only write "const int& a" (well, "const string& s" maybe, to make it worthwhile), and only in a parameter list.
Just because you *can* do something doesn't mean you *should*. Sometimes the equivalence of foo[3] and 3[foo] is really useful. I've never seen that happen, and wouldn't use it lightly, but remember Duff's device.
Firstly, I have fairly strong objections to the Stroustrup miscuddling (`int* x'). Secondly, I can think of a good reason to want to declare different levels of indirection in one line.
Consider the common case of building a list in the correct order.
That's odd, I seem to be the only person so far to admit to "int *x; int& x". I blame the boss; I picked up C++ by being dropped into the middle of a sizable codebase and told "here's a least of new features to implement", so I mimic his style, except where my own habits take over.
I don't do C++ unless I really have to. In a recent project I have had too and refactored most of it into C, leaving the bizarro stuff I can't be bothered sorting out in C++ (one of those projects).
I think C++ is probably the worst mistake the computing industry has ever made, when you include the extent to which it is used as well as its degree of inherent evilness. Its invention and use must have cost billions of pounds, at least.
Apart from the inherent language issues with the function pointer stuff, which I don't pretend to understand, I find it hard to comprehend how int* people deal with things like struct foo *a,*b,c,d;
(no subject)
Date: 2006-04-11 09:01 am (UTC)I had to double-check that C++ references worked the same way; since Stroustrup believes in the wrong notation for pointers, I had a nasty feeling he might have built the wrong semantics into his bit of the language. But no; "int&x,y" declares y to be an int, not a reference, so regardless of Stroustrup's own silly spacing convention the same rule applies for sane people.
(no subject)
Date: 2006-04-11 09:02 am (UTC)(no subject)
Date: 2006-04-11 09:05 am (UTC)http://www.csse.monash.edu.au/~damian/papers/HTML/ModestProposal.html
(no subject)
Date: 2006-04-11 09:09 am (UTC)More generally I like a 'minimal criminal' form of Hungarian notation where I slap a 'p' to the front for each layer of indirection when it is known (int* pX; int** ppX; etc.).
(no subject)
Date: 2006-04-11 09:11 am (UTC)(no subject)
Date: 2006-04-11 09:21 am (UTC)I suppose it would work if you were operating in a closed community of C programmers who had all adopted the same coding style, but this is the real world and like everybody else you have to read code written in a wide variety of styles. Does it not therefore make sense to go with rather than against the intended usage of the language, so that code written in any style is just as legible to you?
(no subject)
Date: 2006-04-11 09:34 am (UTC)Does it not therefore make sense to go with rather than against the intended usage of the language, so that code written in any style is just as legible to you?
Yes unless that usage is completely confusing. Doing
is valid in the language but I'd never do that 'cos of the confusion it'd generate.
(no subject)
From:(no subject)
From:(no subject)
Date: 2006-04-11 09:10 am (UTC)(no subject)
Date: 2006-04-11 09:13 am (UTC)[1] Modulo auto-boxing weirdness.
(no subject)
From:(no subject)
From:Autoboxing
From:Re: Autoboxing
From:Re: Autoboxing
From:Re: Autoboxing
From:Re: Autoboxing
From:Re: Autoboxing
From:Re: Autoboxing
From:Re: Autoboxing
From:Re: Autoboxing
From:Re: Autoboxing
From:Re: Autoboxing
From:(no subject)
Date: 2006-04-11 09:16 am (UTC)int x;declaresxto be anint(i.e. an integer),int *x;declaresxto be a pointer to an integer. Strictly, it declares that*xis anint. Is that clear? :)FTR
*ymeans "value pointed to byy", similarly&zmeans "address ofz".(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
Date: 2006-04-11 09:16 am (UTC)int* x;as it mimics the mental description I use - I read that as "int-pointer x". Correctness of C/C++ style is probably not very high on my list of Important Life Skills, it must be said... (nor, for that matter, is 'Ability to write C++')At least I'm in the majority on
int &x;^_^;(no subject)
Date: 2006-04-11 09:20 am (UTC)And with that, I'm back to programming in Java. Have fun ^_^
(no subject)
Date: 2006-04-11 09:54 am (UTC)Correctness of C/C++ style is probably not very high on my list of Important Life Skills
Correctness isn't but consistency within a project is. Generally coding styles are religious wars so it is probably best if one is at least aware of your own personal gotchas but try to avoid them if you ever have any wiggle room.
burn the heretic!
From:Re: burn the heretic!
From:Re: burn the heretic!
From:Re: burn the heretic!
From:(no subject)
Date: 2006-04-11 09:25 am (UTC)This is why, whenever I get to the "pointers" section while trying to learn C or C++, m brain explodes.
I think I'll stick to perl and shell.
(no subject)
Date: 2006-04-11 09:39 am (UTC)(no subject)
From:(no subject)
Date: 2006-04-11 09:37 am (UTC)(no subject)
Date: 2006-04-11 09:46 am (UTC)I see that
Still, I can see why someone might want to write it the other way, since *x = 0; is not at all the same as int *x = 0;
(no subject)
Date: 2006-04-11 10:20 am (UTC)Declaring more than one variable per line is fine for simple types, but types should not be mixed, no matter how legal. "int a, *b, c;" is valid, but bad, as it declares two ints and a pointer in a single statement. Too much information in very little space is the lifeblood of the IOCCC, for a good reason. Multiple identical structs should for the same readability reason not be declared as "struct { ... } foo,bar;".
In C++, classes are essentially "complex types"; references should only ever be used to pass classes by value, as const references. Everything else has far too much potential for bugs, unreadability, and confusion. A const& has the advantage of not needing a copy constructor (often dangerous for complex classes, which may need to do all sorts of initialisation on construction, almost always pointless overhead) while preserving by-value semantics (being read-only but directly usable without requiring careful dereferencing).
So. I write "int main(int argc, char* argv[])" to make explicit that argv is an array of char*. I write "int* a;", or "int *a, *b;" if I really need more than once. I also prefer C++ in oh so many ways, but would only write "const int& a" (well, "const string& s" maybe, to make it worthwhile), and only in a parameter list.
Just because you *can* do something doesn't mean you *should*. Sometimes the equivalence of foo[3] and 3[foo] is really useful. I've never seen that happen, and wouldn't use it lightly, but remember Duff's device.
(no subject)
Date: 2006-04-11 10:41 am (UTC)(no subject)
Date: 2006-04-11 10:38 am (UTC)Consider the common case of building a list in the correct order.
node *n, *head, **tail = &head; thing x; while ((x = getthing()) != END_MARKER) { n = CREATE(node); n->thing = x; *tail = n; tail = &n->next; } *tail = 0;It just looks silly to me to have to declare head and tail on different lines just because of the difference in indirection levels.Oh, and thirdly, C++ references are just evil and wrong.
(no subject)
Date: 2006-04-11 11:12 am (UTC)(no subject)
From:(no subject)
Date: 2006-04-11 11:17 am (UTC)(no subject)
Date: 2006-04-11 11:18 am (UTC)I think C++ is probably the worst mistake the computing industry has ever made, when you include the extent to which it is used as well as its degree of inherent evilness. Its invention and use must have cost billions of pounds, at least.
(no subject)
Date: 2006-04-11 11:20 am (UTC)(no subject)
Date: 2006-04-11 11:21 am (UTC)