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.

  • 6
    @Mark: How is that, given that I specifically exclude that case? There is no identifier here. –  Sep 27 '10 at 10:15
  • Where are you getting "seems much more common"? What code bases are you looking at to get that conclusion? – David Thornley Sep 27 '10 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..." –  Sep 27 '10 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 03 '13 at 08:48

4 Answers4

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.

dwc
  • 2,016
  • 1
  • 14
  • 4
  • 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 '11 at 09: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 04 '12 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 03 '13 at 08: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.)

mipadi
  • 7,493
  • 36
  • 35
  • 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). –  Sep 27 '10 at 15:21
  • I don't use brackets to denote function arguments that are "arrays". I'd use `void f(char *)`. – mipadi Sep 27 '10 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. –  Sep 27 '10 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 '10 at 15:35
  • Ugh, mismatched parentheses. http://xkcd.com/541/ – Joe D Nov 03 '10 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.

doug65536
  • 198
  • 2
  • 7
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.

John Bode
  • 10,826
  • 1
  • 31
  • 43
  • It's not a "paradigm". Please try your "C++" syntax to declare two pointers in one statement. – doug65536 Feb 03 '13 at 08: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 03 '13 at 14:46