12

Possible Duplicate:
int* i; or int *i; or int * i;

Thinking about where we place our asterisks; how do those that prefer to keep the "pointerness" away from the type and with the identifier (int *i) write code when the identifier is missing?

void f(int*); // 1
void f(int *); // 2

The former seems much more common, no matter what your preference when with the identifier. Is this a special case? What makes it an exception?

However, the first still isn't universal, because I have seen the latter style. Besides consistency along the lines of "there's always a space with the identifier, so we have one without", are there any other reasons to prefer it?

What about casts or array and function types? How would you re-write these:

(void*)var /*or*/ (void *)var

int[3] /*or*/ int [3]
// more relevant in C++ than C: Example<int[3]>

void(int) /*or*/ void (int)
// more relevant in C++ than C: std::function<void(int)>

The latter two would rarely, if ever, be used in C, but are seen with C++ templates.

4
  • 6
    @Mark: How is that, given that I specifically exclude that case? There is no identifier here.
    – Roger Pate
    Sep 27, 2010 at 10:15
  • Where are you getting "seems much more common"? What code bases are you looking at to get that conclusion? Sep 27, 2010 at 16:40
  • @David: "Seems much more common" to me, given code I just happen to see in general (including public places such as SO). Biased, I know. I might rephrase as "if you prefer the asterisk with the identifier but also prefer #1..."
    – Roger Pate
    Sep 27, 2010 at 16:42
  • People who really understand C put the * with the name because they know the * is associated with the name, not the type.
    – doug65536
    Feb 3, 2013 at 8:48

4 Answers 4

16

The goal should be to make the code readable and clear. The style int* a; may seem fine, but when it becomes int* a, b; it implies something different than what it really is. Contrast with int *a, b; and int *a, *b; where each reads exactly like the way it works.

The difference between void f(int*); and void f(int *); for readability is negligible, and I can't find myself caring much which one is used.

When you remember the top level goal (readability) it's easier to separate pure nitpicks from potential comprehension/maintenance problems.

3
  • 12
    As a rule, at code review, we reject anything that defines two variables on one line such as int a, b;, largely because of the problems you have discussed.
    – mattnz
    May 11, 2011 at 9:18
  • I always wonder about this. I see the point of course. However I've never seen this cause anything worse than a one off compiler error when the code fails to compile, which gets immediately fixed. I've never seen it cause a bug in a released program. However splitting your definitions over several lines makes the code bigger and potentially slightly harder to read and understand and I certainly have seen that cause bugs in released code. That said, I still do it your way :)
    – JohnB
    Apr 4, 2012 at 16:35
  • Unfortunately, the important point in your answer is stated so cryptically, the reader can just map their current erroneous understanding onto it and it fits. You weren't at all clear that 'b' in your first example is not a pointer.
    – doug65536
    Feb 3, 2013 at 8:20
6

I always separate the star from the type, so I use:

void f(int *);

void f(int *x)
{
    char *y = (char *) x;
    char x[4];
}

Obviously, I don't separate the brackets from the identifier.

That's how I learned to do it from K&R, and who am I to argue? (Also, it seems to be the most readable way.)

5
  • For array types, I also meant without the identifier: void f(char[4]) /*or*/ void f(char [4]) (guess that's also more relevant to C++ than C in the same way: as a template type argument).
    – Roger Pate
    Sep 27, 2010 at 15:21
  • I don't use brackets to denote function arguments that are "arrays". I'd use void f(char *).
    – mipadi
    Sep 27, 2010 at 15:23
  • I don't in this exact case either, and if I'm passing references (C++, ofc.) or pointers to arrays, there's something in between. I figured it'd show you what I meant, though.
    – Roger Pate
    Sep 27, 2010 at 15:30
  • I rarely write C++ code (I try to avoid it as much as possible ;) ), so any C++ code I write generally followed my ingrained C-isms.
    – mipadi
    Sep 27, 2010 at 15:35
  • Ugh, mismatched parentheses. xkcd.com/541
    – Joe D
    Nov 3, 2010 at 19:01
2

It is definitely NOT about style, or readability, or maintainability, or anything aesthetic.

The syntax of C, and therefore also C++, require it.

Here's an example:

int *a, *b, *c;

That makes three pointers.

However:

int* a, b, c;

That makes a pointer, and two ints.

1

Unless specifically instructed otherwise, I tend to follow the C paradigm for stuff like that; namely, T *, T [N], T (*)(), etc., whether I'm writing C or C++, because pointer-ness and array-ness and function-ness are all functions of the declarator, not the type specifier.

However, I will follow the common paradigm for the given language when declaring objects:

T* foo; // C++
T *bar; // C

Is this an inconsistency in my coding style? Yes. Is it a big deal? Not until someone complains about it.

2
  • It's not a "paradigm". Please try your "C++" syntax to declare two pointers in one statement.
    – doug65536
    Feb 3, 2013 at 8:17
  • @doug65536: When I write C++, I follow the C++ convention (is that a better word?) and declare one pointer per declaration statement. It's just easier when working on a team to follow the team conventions, even when they're objectively wrong.
    – John Bode
    Feb 3, 2013 at 14:46