tags:

views:

1752

answers:

17

I know this is about as bad as it gets for "religious" issues, as Jeff calls them. But I want to know why the people who disagree with me on this do so, and hear their justification for their horrific style. I googled for a while and couldn't find a style guide talking about this.

So here's how I feel pointers (and references) should be declared:

int* pointer = NULL;
int& ref = *pointer;
int*& pointer_ref = pointer;

The asterisk or ampersand goes with the type, because it modifies the type of the variable being declared.

EDIT: I hate to keep repeating the word, but when I say it modifies the type I'm speaking semantically. "int* something;" would translate into English as something like "I declare something, which is a pointer to an integer." The "pointer" goes along with the "integer" much more so than it does with the "something." In contrast, the other uses of the ampersand and asterisk, as address-of and dereferencing operators, act on a variable.

Here are the other two styles (maybe there are more but I really hope not):

int *ugly_but_common;
int * uglier_but_fortunately_less_common;

Why? Really, why? I can never think of a case where the second is appropriate, and the first only suitable perhaps with something like:

int *hag, *beast;

But come now... multiple variable declarations on one line is kind of ugly form in itself already.

+2  A: 

In C# code, I prefer the int* x; to int *x; as * belongs to the type, but in C/C++, * belongs to the variable, not the type, so the int *x; habit will be less prone to errors.

Mehrdad Afshari
Semantically I'd still say it goes with the type in C/C++...
Owen
But, if you write int* x, y; to declare x,y as pointers, you'd get into trouble.
Mehrdad Afshari
Yeah, that's what I was addressing in my last couple of paragraphs. I figure semantics should be what dictates style, so if that means you have to implement another rule of only one declaration per line, then so be it.
Owen
I agree with Owen, you are declaring a "pointer to int", to me semantically it belongs with the type.
ceretullis
+14  A: 

In C and C++ the * modifies the variable, not the type and belongs with the variable, as is proved by:

int *abc,def;

What's def, an int or a pointer?

In C# it modifies the type and belongs with the type.

In Java, there's not such notion. I don't follow your 0/NULL/null remark.

Software Monkey
Yeah... I removed that remark. It's late and apparently my brain's off. Enough to post a subjective question on SO, at least. As for your example of potential confusion, that's what I was alluding to in the last example I gave.
Owen
And wrt your first line, as I keep repeating, style is about semantics, and semantically the type is what is modified: abc is being declared as a "pointer to an int"—that's its type. (This is as opposed to the other use of *, which is an operator modifying the variable, dereferencing it.)
Owen
But the * isn't applied to the type (else it would impact all variables declared in that statement), it is applied to abc only; you might think it ought to be applied to the type, but the coding style should reflect the reality of the language, not what you wish the reality to be.
Software Monkey
Syntax vs (my favourite word, apparently) semantics... Style should reflect what my intent is when I write a line of code. Just because a language allows or imposes something doesn't mean it's what should be taken as gospel. I can say i=j=k=0; or if(somePointer) {...} — doesn't mean it's good style.
Owen
I agree - but to choose a style that infers an incorrect binding is misleading to the programmer who comes after you. What if someone who is less experience sees "int* abc;" and adds the "...,def;" expecting def to be a pointer?
Software Monkey
When I talk of the * "modifying," I'm speaking of the modification of the meaning of a statement, at a conceptual level. In a declaration, the * doesn't modify the meaning of the variable name, it modifies the type that the variable will have. Re: adding ",def": They should add a new line instead.
Owen
Meet ya in the middle - declare your variable as (int*) abc,...; and you're golden. You have your intent expressed and the language actually enforces your intent.
Software Monkey
Heh, all right then. And I didn't actually know that was valid syntax! Innerestin...
Owen
ha ha - don't quote me on it, my C's a little rusty, but I'm 99% sure. I am going to watch some TV and turn in.
Software Monkey
And this is what D also does. It's much better this way.
Tim Matthews
+5  A: 

I think that * refers to the type and always write Type* t.

Type t;  // type is 'Type'
Type* t; // type is 'a reference to Type'

So *t means dereferencing.

abatishchev
+3  A: 

For clarity I sometimes use tabs between types and variable names with I declare structs:

struct something_s {
    int            *foo;
    unsigned int   bar;
};

is clearer than:

struct something_s {
    int *foo;
    unsigned int bar;
};

for my eyes.

So putting the * near the variable name istead of the type is more convenient for me.

Leeor Aharon
I agree with the readability. However there is one minor inconvenience: if you change the 'unsigned int bar' variable, you not only have to change this line but also the line above and below to fix the indentation.So if you use version control, make sure you disable whitespace checking when compare.
Roalt
The indentation doesn't impact where the * should go... In fact this scenario is one where having the * on the right bugs me most! Sometimes in a function declaration with this formatting, I'll look down the left column to see what types are required; I'll only see *'s if they're on the left.
Owen
+2  A: 

int* pStuff ....... pStuff's type is "pointer to an int"

int stuff ........ stuff's type is "int"

Especially true since you can write

typedef int* pInt;

pInt pStuff;

This emphasizes quite well what I've meant by "it modifies the type"...
Owen
WOW! I never actually thought about that, but its a great point towards int* pStuff
Robert Gould
What about leaving pointers out of typedef statements?
TomWij
@Tom: What about it? If you mean leaving them out would be a good idea, then I concur. If I see a type called something like IntPtr my first thought is that it's a smart pointer of some kind, not just a typedeffed int*.
Owen
+3  A: 

As long as the source code sticks to one notation or the other I don't really mind... it's when the source mixes both methods that it becomes an annoyance for me.

NathanE
+1  A: 

Currently living in the MFC world, where the hungarian notation is quite common, I use to handle it the same way as you, Owen.

My code then looks slightly different with pointer variables having a p prefix:

int* pFoo = NULL;

With the prefix it would simply be redundant to put the asterisk next to the variable name.


I also agree with you on the rule not to declare several variables on one line for some reasons:

  • The obvious: No questions about the type of variables arise when declaring pointers and references.
  • It encourages declaring a variable right where it's needed because one doesn't save any typing effort anyway. This helps to avoid C-style declarations at the beginning of a function, which I believe is not a good practice.
  • It's easier to change the type of a variable.
mxp
Further to the point of declaring variables right where they're needed, having a single line may make one more likely to provide initializations provided, as putting initializations on a line with multiple declarations can become particularly illegible and may be shied away from for that reason...
Owen
+6  A: 

I'm one of those "evil" guys who like the free standing asterisk. I like it because it looks best in my eyes. Of course you can argue that int* should be read as pointer to int, but this, as mentioned before, doesn't work with multiple declarations. And since we all know the common pitfalls and they also lead to compile errors and not to hidden bugs, it is simply a matter of taste and what you are used to.


char *start, *end;   // or
char * start, * end; // looks simply nicer then
char* start,* end;

And I don't think that every variable declaration belongs in its own line. In this case start and end are belonging together. But this is also a matter of taste and habit.

quinmars
A: 

Each declaration gets it own line. I use the * symbol next to the variable.

int *pointer = new int(1);
TomWij
+12  A: 

According to the AV rule 62 of the JFS C++ Coding Standards:

The dereference operator '*' and the address-of operator '&' will be directly connected with the type-specifier.

Rationale: The int32* p; form emphasizes type over syntax while the int32 *p; form emphasizes syntax over type. Although both forms are equally valid C++, the heavy emphasis on types in C++ suggests that int32* p; is the preferable form.

Examples:

int32* p;  // Correct 
int32 *p;  // Incorrect
int32* p, q;  // Probably error. However, this declaration cannot occur under
              // the one name per declaration style required by AV Rule 152.

P.S. Will rules are "expected to be followed".

Ryan
+37  A: 
discomurray
Good find; what's the source?
Owen
Bjarne's Quote is from 'Bjarne Stroustrup's C++ Style and Technique FAQ' @ http://www.research.att.com/~bs/bs_faq2.html
discomurray
This should be the accepted answer...
Noldorin
+1  A: 

From a compiler's (or a compiler writer's) point of view, the expression "int *p" is resolved as follows:

  1. Read from left to right, find the first identifier, which is "p";
  2. Look right, there's nothing;
  3. Look left, it's a "*", so the compiler determines that p is a pointer;
  4. Look right, there's nothing;
  5. Look left, it's an "int", so the thing that gets pointed to by p is an int.

That's why you see "int *p" in a lot of C code rather than "int* p". Of course, whether you should use one style instead of another is purely a question of personal taste. Like vi and emacs thing.

BTW, I recently read a lot of C code from MS. Very ugly, consistently ugly.

PolyThinker
+22  A: 
int *ugly_but_common;

is not ugly, and neither is:

int *hag, *beast;

nor even:

int witch, *ghost, goblin; // this must really confuse you.

All of them are simply saying *ugly_but_common (or *hag or *beast, or whatever) is of int type. This is not to be confused with ugly_but_common which is of pointer-to-int type. The last witch/ghost/goblin is used in a K&R tutorial (http://www.lysator.liu.se/c/bwk-tutor.html#pointers), though with less colorful names.

This is always the style K&R uses, for the reason I explained (I don't have the book with me, so I can't give a quote. Check for yourself).

Matthew Flaschen
Interesting! You've expanded my mind; thank you. That's an excellent point on a different angle from which to see the declaration. Here, have an accepted answer, because this is the most enlightening view I've read yet. (I'm probably just dense though.)
Owen
Looking back a month later I see that I was (unsurprisingly) indeed being dense. Part of the Bjarne quote from discomurray indicated the same possible emphasis of syntax. Sadly, my reading of his post was hindered by some *s being confused for markdown and creating confusing formatting.
Owen
Johannes Schaub - litb
Dave
A: 

There are lots of reasons why int *pi=NULL; is wrong and int* pi=NULL; is right:

1) int* is a type and you can typedef it as such if necessary (typedef int* INT_PTR;), then you can INT_PTR pi=NULL;

2) you *can* put multiple declarations on a line ... if you are a pathalogic idiot, but you'll confuse youself if you use a typedef as INT_PTR pi, pj; does declare 2 pointers

3) if you do int *pi; you will never be able to declare a constant pointer which must be delcared - int* const pi; or a constant pointer to a constant int - const int* const pi; (you could even type def this - typedef const int* const CONST_INT_CONST_PTR;)

QED there is only one right way, though you will get an awful lot of narrow minded whingers who will blindly defend their indefensible position - they should all be put in a special home for people with outdated skillsets :-)

A: 

Which do you prefer?

int[10] arr;
int arr[10];

In C (I can't say about C++ or C#), the first option is a syntax error, so I write my pointers as my arrays

int *ptr;
pmg
I actually wish that `int[10] arr` was legal, and that `int* ptr` was the only legal place to put the asterisk. It would make variable declarations much more consistent. I would prefer that `type name`, such as `int x` were the way everything be declared.
Darryl
A: 

The argument that * and & modify the type as opposed to the declarator is spurious, as it is inconsistent with every other type; for example, we don't declare an object of type "N-element array of T" as T[N] a, nor do we declare an object of type "function returning T" as T() f. For something like a pointer to an array or a pointer to function, the * must be explicitly bound to the declarator as in T (*a)[N] or T (*f)(). Writing something like T* a[N] just indicates confused thinking AFAIC.

John Bode
A: 

It doesn't matter, it is personal preference.

Some people like to keep the type together:

int* p;

Other people say that it should go next to the variable because of the following:

int *p, x;//declare 1 int pointer and 1 int
int *p, *x;//declare 2 int pointers.

Over time you will just overlook this and accept both variations.

Brian R. Bondy