Placement of the asterisk in pointer declarations

40,552

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:

  1. 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...

  2. Keep doing this in a spiral/clockwise direction until all tokens have been covered.
  3. 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.

Share:
40,552

Related videos on Youtube

Michael Stum
Author by

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, 2022

Comments

  • Michael Stum
    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:

    1. int* test;
    2. int *test;
    3. int * test;
    4. int* test,test2;
    5. int *test,test2;
    6. 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
      Sulthan almost 12 years
      In C/C++ white spaces don't change meaning.
    • Jin Kwon
      Jin Kwon almost 9 years
      7. int*test;?
    • vastlysuperiorman
      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
      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
      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
      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
      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 out int, *, and test. It will still be parsed as int (*test).
    • endolith
      endolith about 3 years
      I 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 that int *test,test2; is correct.
    • Eljay
      Eljay about 2 years
      ...and that int* test; int test2; is correct.
    • Michael Chourdakis
      Michael Chourdakis about 2 years
      I guess that was another reason that smart pointers were created. To avoid the asterisk at all.
  • Michael Stum
    Michael Stum over 15 years
    So 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
    Joe Phillips over 15 years
    @ Michael Stum It's C++ so do you really think there is a logical explanation?
  • Ferruccio
    Ferruccio over 15 years
    Read K&R (The C Programming Language). It explains all this very clearly.
  • Michael Stum
    Michael Stum over 15 years
    Noted, 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
    Michael Burr over 15 years
    Cases 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
    Joe Phillips over 15 years
    That looks daunting and quite horrible, sorry to say.
  • ephemient
    ephemient over 15 years
    Whitespace 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
    Michael Stum over 15 years
    it does, but it seems quite a good explanation for some of the more complicated constructs
  • Michael Burr
    Michael Burr over 15 years
    @d03boy: There's no question - C/C++ declarations can be a nightmare.
  • Admin
    Admin almost 11 years
    the 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
    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
    yyny over 8 years
    Yet writing char* a[100]; also deduces that *a[42]; will be a char and a[42]; a char pointer.
  • Michel Billaud
    Michel Billaud over 8 years
    Well, we all deduce the same conclusions, only the order is varying.
  • Stefan Dragnev
    Stefan Dragnev about 8 years
    #include <windows.h>LPINT test, test2;
  • v.oddou
    v.oddou about 7 years
    this is bogus, what do you call int *MyFunc(void) ? a *MyFunc is a function returning an int ? no. Obviously we should write int* MyFunc(void), and say MyFunc is a function returning a int*. 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
    underscore_d about 7 years
    This 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
    Ruslan over 6 years
    The "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 -- Слава Україні
    Antti Haapala -- Слава Україні over 5 years
    But *MyFunc() is an int. The problem with the C syntax is mixing prefix and postfix syntax - if only postfix was used, there would be no confusion.
  • Adrian McCarthy
    Adrian McCarthy about 5 years
    I 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 traditional int *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
    Adrian McCarthy about 5 years
    The first camp fights the language's syntax, leading to confusing constructs like int const* x;, which I find as misleading as a * x+b * y.
  • deLock
    deLock almost 5 years
    Quote: "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
    Michel Billaud almost 5 years
    If you prefer the other way, say a[42] is a char pointer, and *a[42] is a char.
  • shevy
    shevy about 4 years
    Well - 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
    shevy about 4 years
    While 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
    Scott Langham about 4 years
    Unfortunately 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
    Peter - Reinstate Monica almost 4 years
    It'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
    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 is int p; int *i;).
  • Lou
    Lou about 3 years
    This is the best answer to this question. It should be higher voted.
  • TallChuck
    TallChuck over 2 years
    Interestingly, the declaration int *ip = 0, i = 0 initializes ip = (int*) 0and i = (int) 0, so the expression syntax mimicking doesn't extend to the assignment operator