5

Both of the following are valid pointer declarations in C/C++:

int *x;
int* x;

The former seems to be preferred by seasoned C/C++ programmers. I personally find the latter to be easier to understand - it illustrates that pointer-ness is a factor of the variable's type, not its name. Furthermore, this unifies stylistically the declaration of pointers and functions returning pointers:

int* foo(); //foo returns an int*
int* x;     //x is an int*
int *foo(); //generally unused (in my experience)
int *x;     //feels wrong in this context

int *x seems counter-intuitive despite being the norm, so I feel I must be overlooking something.

What motivates syntactic preference regarding pointer declaration in C/C++?

5
  • To me it's usually the latter with C++ devs, same with int& x instead of int &x. The reasoning is usually because there's a stronger emphasis on types in C++, and so C++ developers often want to look at int* as one indivisible thing -- a completely different data type from int with a different interface. Also helps to keep it uniform when you want to do like vector<int*> as opposed to vector<int *>.
    – user204677
    Dec 8, 2017 at 3:53
  • @DrunkCoder Yeah! That's the conclusion I came to after reading some of the answers on the questions this was dupe-closed to. C: int *x - what's the int? *x. C++: int* x - what's x? an int*.
    – Conduit
    Dec 8, 2017 at 4:02
  • I've settled on the latter style but started with the former in C, following K&R style originally... then worked with a bunch of C++ colleagues doing the latter way and that rubbed off on me after a while. It would be so much easier if, say, int* x, y defined two pointers instead of one pointer and one integer. That's really confusing when you want to think of int* as like an indivisible thing. That said, I got used to a coding standard where it was forbidden to define more than one variable per line.
    – user204677
    Dec 8, 2017 at 4:06
  • T *ptr; reflects how the grammar actually works - the * is part of the declarator, not the type specifier. It’s the same reason we don’t write T[N] array; or T() func. Pointer-ness, array-ness, and function-ness are specified in the declarator. You can write T* p or T *p or T * p or even T*p - they will all be parsed as T (*p).
    – John Bode
    Dec 13, 2017 at 13:42
  • Secondly, this style only works for simple object pointers - it won’t work for array or function pointers - T (*ap)[N], T (*fp)(...), T (*afp())[M], etc. Think about the prototype for the signal function, and how you would apply the T* convention to it cleanly (it would require at least one typedef, which, IMO, obscures more than it clarifies).
    – John Bode
    Dec 13, 2017 at 13:52

1 Answer 1

5

Both forms have exactly the same syntax. They differ only by spacing arrangements.

The first form is preferred because it reflects well the semantic: the pointer is only for the variable that immediately follows the star:

int *p, a; // p is pointer, a is plain int

The second form could be misleading, because it gives the impression that the pointer belongs to the type and would be applicable for all the variables in the same statement:

int* p, a; // still, only p is pointer, a is plain int despite impressions
8
  • As a matter of style I never declare variables in this way for precisely the reasons you stated. Dec 7, 2017 at 17:47
  • 1
    I agree with this answer for C, however, I'd point to this on Bjarne Stroustrup's page for C++ stroustrup.com/bs_faq2.html#whitespace Dec 7, 2017 at 17:58
  • @BenCottrell interesting point. However despite Stroustrup's preference for the emphasis on type, he did not change the syntactic precedence rules, because he wanted to stay as much compatible with the C heritage as possible (see his book "Design and evolution of C++"). So his style is not in line with semantic. Later, when template got introduced into the language, Stroustrup didn't either introduce a std::raw_ptr<type> which would have had the advantage of type emphasis AND consistency with precedence, while preserving the heritage. Certainly because it's only a style question.
    – Christophe
    Dec 7, 2017 at 18:18
  • I wasn't aware of that - good reasoning
    – Conduit
    Dec 7, 2017 at 18:19
  • @RobertHarvey I fully agree ! One declaration per statement. And anyway, who needs raw pointers when we have containers, move semantics and smart pointers ? Nevertheless I didn't find a shorter way to explain the semantic issue related to the grammatical rule. Ultimately, it's just a question of style. But there's lot of legacy code out there that remains to be maintained with mixed styles, so I really wanted to make this semantic point to draw attention on this source of errors.
    – Christophe
    Dec 7, 2017 at 18:29

Not the answer you're looking for? Browse other questions tagged or ask your own question.