Placement of the asterisk in pointer declarations
Solution 1
4, 5, and 6 are the same thing, only test is a pointer. If you want two pointers, you should use:
int *test, *test2;
Or, even better (to make everything clear):
int* test;
int* test2;
Solution 2
White space around asterisks have no significance. All three mean the same thing:
int* test;
int *test;
int * test;
The "int *var1, var2
" is an evil syntax that is just meant to confuse people and should be avoided. It expands to:
int *var1;
int var2;
Solution 3
Many coding guidelines recommend that you only declare one variable per line. This avoids any confusion of the sort you had before asking this question. Most C++ programmers I've worked with seem to stick to this.
A bit of an aside I know, but something I found useful is to read declarations backwards.
int* test; // test is a pointer to an int
This starts to work very well, especially when you start declaring const pointers and it gets tricky to know whether it's the pointer that's const, or whether its the thing the pointer is pointing at that is const.
int* const test; // test is a const pointer to an int
int const * test; // test is a pointer to a const int ... but many people write this as
const int * test; // test is a pointer to an int that's const
Solution 4
Use the "Clockwise Spiral Rule" to help parse C/C++ declarations;
There are three simple steps to follow:
Starting with the unknown element, move in a spiral/clockwise direction; when encountering the following elements replace them with the corresponding english statements:
[X]
or[]
: Array X size of... or Array undefined size of...
(type1, type2)
: function passing type1 and type2 returning...
*
: pointer(s) to...- Keep doing this in a spiral/clockwise direction until all tokens have been covered.
- Always resolve anything in parenthesis first!
Also, declarations should be in separate statements when possible (which is true the vast majority of times).
Solution 5
As others mentioned, 4, 5, and 6 are the same. Often, people use these examples to make the argument that the *
belongs with the variable instead of the type. While it's an issue of style, there is some debate as to whether you should think of and write it this way:
int* x; // "x is a pointer to int"
or this way:
int *x; // "*x is an int"
FWIW I'm in the first camp, but the reason others make the argument for the second form is that it (mostly) solves this particular problem:
int* x,y; // "x is a pointer to int, y is an int"
which is potentially misleading; instead you would write either
int *x,y; // it's a little clearer what is going on here
or if you really want two pointers,
int *x, *y; // two pointers
Personally, I say keep it to one variable per line, then it doesn't matter which style you prefer.
Related videos on Youtube
Michael Stum
The same thing we do every night, Pinky. Try to take over the world! Full-Stack Developer on Stack Overflow Enterprise, working to make our little corner of the Internet better for all of us.
Updated on July 08, 2022Comments
-
Michael Stum almost 2 years
I've recently decided that I just have to finally learn C/C++, and there is one thing I do not really understand about pointers or more precisely, their definition.
How about these examples:
int* test;
int *test;
int * test;
int* test,test2;
int *test,test2;
int * test,test2;
Now, to my understanding, the first three cases are all doing the same: Test is not an int, but a pointer to one.
The second set of examples is a bit more tricky. In case 4, both test and test2 will be pointers to an int, whereas in case 5, only test is a pointer, whereas test2 is a "real" int. What about case 6? Same as case 5?
-
Sulthan almost 12 yearsIn C/C++ white spaces don't change meaning.
-
Jin Kwon almost 9 years7.
int*test;
? -
vastlysuperiorman about 8 years+1 because I'd only thought to ask about 1 - 3. Reading this question taught me something about 4 - 6 that I'd never thought of.
-
AnorZaken almost 8 years@Sulthan That is true 99% of the time, but not always. Of the top of my head there was the type of templated type in templated type space requirement (pre C++11). In
Foo<Bar<char>>
the>>
had to be written> >
so as not to be treated as a right-shift. -
Sulthan almost 8 years@AnorZaken You are right, that's a rather old comment. There are multiple situations when a space will change meaning, for example, the increment
++
operator cannot be split by a space, identifiers cannot be split by a space (and the result can be still legal for the compiler but with undefined runtime behavior). The exact situations are very difficult to define considering the syntax mess that C/C++ is. -
AnorZaken almost 8 years@Sulthan yes those cases you mention now should be rather obvious, I meant that there are a few non-obvious cases where a space is required. Anyway I just wanted to make that note for the record, it wasn't meant as criticism to your comment.
-
John Bode over 3 years@JinKwon: Whitespace is only necessary to separate tokens that can't otherwise be distinguished. Since
*
is not part of any identifier (it's a token all on its own), no whitespace is necessary to separate outint
,*
, andtest
. It will still be parsed asint (*test)
. -
endolith about 3 yearsI don't understand why people keep saying this is "just aesthetics" or "style" or "a matter of opinion". The fact that
int* test,test2;
doesn't do what you would expect implies that it is wrong, a result of misunderstanding the language, and thatint *test,test2;
is correct. -
Eljay about 2 years...and that
int* test; int test2;
is correct. -
Michael Chourdakis about 2 yearsI guess that was another reason that smart pointers were created. To avoid the asterisk at all.
-
Michael Stum over 15 yearsSo Case 4 is actually a death-trap then? Is there any specification or further reading that explains why int* test,test2 only makes the first variable a pointer?
-
Joe Phillips over 15 years@ Michael Stum It's C++ so do you really think there is a logical explanation?
-
Ferruccio over 15 yearsRead K&R (The C Programming Language). It explains all this very clearly.
-
Michael Stum over 15 yearsNoted, pretty much everyone recommends that book, i'll grab a copy off Amazon then. But now at least I remember why I was so reluctant to pick up C/C++ in the Past :-)
-
Michael Burr over 15 yearsCases 4, 5 and 6 are "death-traps". This is one reason why many C/C++ style gudes suggest only one declaration per statement.
-
Joe Phillips over 15 yearsThat looks daunting and quite horrible, sorry to say.
-
ephemient over 15 yearsWhitespace is insignificant to a C compiler (ignoring the preprocessor). So no matter how many spaces there are or aren't between the asterisk and its surroundings, it has exactly the same meaning.
-
Michael Stum over 15 yearsit does, but it seems quite a good explanation for some of the more complicated constructs
-
Michael Burr over 15 years@d03boy: There's no question - C/C++ declarations can be a nightmare.
-
Admin almost 11 yearsthe space before or after the asterisk is just a matter of aesthetics. However, the Google Coding standard goes with
int *test
(google-styleguide.googlecode.com/svn/trunk/…). Just be consistent -
Jared Beck about 10 years@SebastianRaschka The Google C++ Style Guide explicitly allows either asterisk placement. Perhaps it has changed since you read it.
-
yyny over 8 yearsYet writing
char* a[100];
also deduces that*a[42];
will be achar
anda[42];
a char pointer. -
Michel Billaud over 8 yearsWell, we all deduce the same conclusions, only the order is varying.
-
Stefan Dragnev about 8 years
#include <windows.h>LPINT test, test2;
-
v.oddou about 7 yearsthis is bogus, what do you call
int *MyFunc(void)
? a*MyFunc
is a function returning anint
? no. Obviously we should writeint* MyFunc(void)
, and sayMyFunc
is a function returning aint*
. So to me this is clear, the C and C++ grammar parsing rules are simply wrong for variable declaration. they should have included pointer qualification as part of the shared type for the whole comma sequence. -
underscore_d about 7 yearsThis doesn't answer the question. Worse, if we try to infer an answer from it, then it implies the asterisk binds to the type at its left, which as everyone else has said, is false. It binds to the single variable name at its right.
-
Ruslan over 6 yearsThe "spiral" doesn't make any sense, much less the "clockwise". I'd rather name it the "right-left rule", since the syntax doesn't make you look right-bottom-left-top, only right-left.
-
Antti Haapala -- Слава Україні over 5 yearsBut
*MyFunc()
is anint
. The problem with the C syntax is mixing prefix and postfix syntax - if only postfix was used, there would be no confusion. -
Adrian McCarthy about 5 yearsI learned this as the "right-left-right" rule. C++ folks often like to pretend all the type information is on the left, which leads to the
int* x;
style rather than the traditionalint *x;
style. Of course, the spacing doesn't matter to the compiler, but it does affect the humans. Denial of the actual syntax leads to style rules that can annoy and confound readers. -
Adrian McCarthy about 5 yearsThe first camp fights the language's syntax, leading to confusing constructs like
int const* x;
, which I find as misleading asa * x+b * y
. -
deLock almost 5 yearsQuote: "says that *a[42] will be a char. And a[42] a char pointer". Are you sure it is not the other way around?
-
Michel Billaud almost 5 yearsIf you prefer the other way, say
a[42]
is achar
pointer, and*a[42]
is a char. -
shevy about 4 yearsWell - the parser appears to allow either variant, but if Dennis and Linus say it should be on the right side, that is quite compelling. But still, we kind of lack some rationale, and then also the explanation why this is done. It's a bit like tab versus space situation - except that one got solved, because people who use spaces rather than tabs, make more money, according to StackOverflow ... :-)
-
shevy about 4 yearsWhile the "one variable per line" seems useful, we still have not completely solved the situation where the asterisk is more to the left, or more to the right. I am quite sure that in code out in the wild one variant prevails; a bit like some countries drive on the right side, and the others drive the wrong direction, such as the UK. ;-)
-
Scott Langham about 4 yearsUnfortunately from my adventures in to the wild I see plenty of both styles. In my team we now use clang-format with a style we've agreed on. This at least means all of the code our team produces has the same style for where the whitespace goes.
-
Peter - Reinstate Monica almost 4 yearsIt's neither "spiral" nor "right-left" nor any other specific pattern: It's simply applying the operators according to parentheses, precedence and respective evaluation order (left-to-right or right-to-left) just like in the corresponding expression which yields the built-in type to the left. Where is your spiral or left-right in
int *arr[1][2][3][4]
?? -
Peter - Reinstate Monica almost 4 years@MichaelStum Death trap?
int *p, i, (*f)();
is a perfectly clear declaration. Just know your language before you use it, and name your variables appropriately (int p, *i;
is a trap, but so isint p; int *i;
). -
Lou about 3 yearsThis is the best answer to this question. It should be higher voted.
-
TallChuck over 2 yearsInterestingly, the declaration
int *ip = 0, i = 0
initializesip = (int*) 0
andi = (int) 0
, so the expression syntax mimicking doesn't extend to the assignment operator