259

Why do most C programmers name variables like this:

int *myVariable;

rather than like this:

int* myVariable;

Both are valid. It seems to me that the asterisk is a part of the type, not a part of the variable name. Can anyone explain this logic?

Lundin
  • 195,001
  • 40
  • 254
  • 396
WBlasko
  • 2,893
  • 2
  • 17
  • 11
  • 1
    The second style seems more intuitive in general, but the former is the way to go to avoid type-related bugs in code. If you're really attached to the latter style, you could always go with `typedefs`, but that will add unnecessary complexity, IMHO. – Cloud Aug 08 '16 at 15:50
  • 1
    Stumbling over here lately adding my part to... Completely disagree with @Cloud in that `typedef`ing pointers is a good idea – this just hides information without any further benefit apart from avoiding variable declaration errors – and for the latter the better approach is not to define more than one single variable at one line of code (while acknowledging that this produces a bit more typing and some more lines of code, but that's still better than the `typedef`...). – Aconcagua Feb 04 '22 at 12:58

12 Answers12

326

They are EXACTLY equivalent. However, in

int *myVariable, myVariable2;

It seems obvious that myVariable has type int*, while myVariable2 has type int. In

int* myVariable, myVariable2;

it may seem obvious that both are of type int*, but that is not correct as myVariable2 has type int.

Therefore, the first programming style is more intuitive.

machine_1
  • 4,266
  • 2
  • 21
  • 42
luiscubal
  • 24,773
  • 9
  • 57
  • 83
  • 170
    perhaps but I wouldn't mix and match types in one declaration. – BobbyShaftoe Dec 30 '08 at 03:13
  • 24
    @BobbyShaftoe Agreed. Even after reading every argument in here, I'm sticking with `int* someVar` for personal projects. It makes more sense. – Alyssa Haroldsen Feb 27 '14 at 23:34
  • 43
    @Kupiakos It only makes more sense until you learn C's declaration syntax based on "declarations follow use". Declarations use the exact same syntax that use of the same-typed variables do. When you declare an array of ints, it does not look like: `int[10] x`. This is simply not C's syntax. The grammar explicitly parses as: `int (*x)`, and not as `(int *) x`, so placing the asterisk on the left is simply misleading and based on a misunderstanding of C declaration syntax. – Peaker Aug 31 '14 at 20:38
  • 9
    Correction: therefore, you should never declare more than one variable on a single line. In general, you shouldn't motivate a certain coding style based on some other unrelated, bad and dangerous coding style. – Lundin Jan 29 '16 at 10:50
  • 8
    This is why I stick to one variable per pointer declaration. There's absolutely no confusion if you do `int* myVariable; int myVariable2;` instead. – Patrick Roberts Apr 11 '18 at 05:24
  • 1
    "it may seem obvious that both are of type int*" Not so obvious, this is a naive argument. Consider `int *const a, b;`. Where does the * "bind"? The type of `a` is `int *const`, so how can you say that the * belongs to the variable when it is part of the type itself? – Lundin Jun 04 '19 at 11:10
  • 1
    @Lundin "Read it the way of the compiler, you must" The compiler groups that as `int` `* const a` `,` `b` `;` at which point it's obvious what's going on. – dgnuff Jun 06 '19 at 17:30
  • I whole-heartedly agree with this answer. Just had to pitch in my cent and a half. My preferred style of variable declaration is to keep variables of the same type defined together. I will usually have a line of `char *buffer = 0, *swap = 0, *outbuff = 0;` I don't know, it just seems neat and organized while efficiently minimizing function height; since compilers take the symbol immediately following the asterisk to be the pointer, to me it has always made sense to put the asterisk immediately before the variable name. – Justin Jack Jul 15 '19 at 15:06
  • 1
    There is also no confusion if you know the rules of the language. Type information should all be together. I think it was a mistake in C to associate asterisks to the right and a mistake to put array information after the identifier. – Pulseczar Apr 29 '21 at 00:10
  • ...Except at the end of Section 6.3.2 in The C++ Programming Language (Bjarne Stroustroup) he specifically says to avoid declarations like this. – Krusty the Clown Dec 15 '21 at 21:13
157

If you look at it another way, *myVariable is of type int, which makes some sense.

biozinc
  • 4,629
  • 2
  • 25
  • 28
  • 6
    This is my favorite explanation, and works well because it explains C's declaration quirks in general--even the disgusting and gnarly function pointer syntax. – Benjamin Pollack Dec 29 '08 at 19:29
  • 16
    It's sort of neat, since you can imagine there isn't any actual pointer types. There are only variables that, when appropriately referenced or dereferenced, gives you one of the primitive types. – biozinc Dec 29 '08 at 19:34
  • 1
    Actually, '*myVariable' may be of type NULL. To make matters worse it could just be a random memory memory location. – qonf Jan 26 '12 at 10:52
  • 4
    qonf: NULL is not a type. `myVariable` can be NULL, in which case `*myVariable` causes a segmentation fault, but there is no type NULL. – Daniel Roethlisberger Jan 09 '13 at 19:02
  • 39
    This point can be misleading in such context: `int x = 5; int *pointer = &x;`, because it suggests we set the int `*pointer` to some value, not the `pointer` itself. – rafalcieslak Feb 23 '13 at 20:04
  • The same logic can also be used for arrays: "int x[10]" means that "x[n] will be an integer" rather than "int[10] x" or "*int x", which means that "x is an array/a pointer to ints". Doing this this way allows for things such as "int x, *y, z[10]", which means that x, *y and z[n] are integers. –  Dec 19 '16 at 17:47
  • @Lundin Yes, ANSI C added the const keyword, which broke "declarations mirror use" a bit. – user109923 Jul 11 '19 at 21:00
  • 1
    Or you declare `myVariable` of the type `int*`, which makes even more sense. Not really an argument imo. – AyCe Apr 22 '20 at 20:27
  • And `myVariable` is of type **pointer to `int`**, or `int*`, which makes complete sense. The asterisk belongs with the type, because a pointer and an `int` are two very different things. Take a more obvious example: `struct MyStruct` can be thousands of bytes in size, but a pointer to a `MyStruct` is only going to be 4 or 8 bytes in size, usually, depending on the machine architecture. The fact that it's a pointer is part of its type information. – Pulseczar Jul 13 '20 at 20:02
73

Something nobody has mentioned here so far is that this asterisk is actually the "dereference operator" in C.

*a = 10;

The line above doesn't mean I want to assign 10 to a, it means I want to assign 10 to whatever memory location a points to. And I have never seen anyone writing

* a = 10;

have you? So the dereference operator is pretty much always written without a space. This is probably to distinguish it from a multiplication broken across multiple lines:

x = a * b * c * d
  * e * f * g;

Here *e would be misleading, wouldn't it?

Okay, now what does the following line actually mean:

int *a;

Most people would say:

It means that a is a pointer to an int value.

This is technically correct, most people like to see/read it that way and that is the way how modern C standards would define it (note that language C itself predates all the ANSI and ISO standards). But it's not the only way to look at it. You can also read this line as follows:

The dereferenced value of a is of type int.

So in fact the asterisk in this declaration can also be seen as a dereference operator, which also explains its placement. And that a is a pointer is not really declared at all, it's implicit by the fact, that the only thing you can actually dereference is a pointer.

The C standard only defines two meanings to the * operator:

  • indirection operator
  • multiplication operator

And indirection is just a single meaning, there is no extra meaning for declaring a pointer, there is just indirection, which is what the dereference operation does, it performs an indirect access, so also within a statement like int *a; this is an indirect access (* means indirect access) and thus the second statement above is much closer to the standard than the first one is.

Mecki
  • 125,244
  • 33
  • 244
  • 253
  • 8
    Thanks for saving me from writing yet another answer here. BTW I usually read the `int a, *b, (*c)();` as something like "declare the following objects as `int`: the object `a`, the object pointed to by `b`, and the object returned from function pointed to by `c`". – Antti Haapala -- Слава Україні May 01 '16 at 07:18
  • 5
    The `*` in `int *a;` is not an operator, and it isn't dereferencing `a` (which is not even defined yet) – M.M Nov 08 '16 at 05:43
  • 1
    @M.M Please name page and line number of any ISO C standard where this standard says that asterisk can be something else than multiplication or indirection. It only shows "pointer declaration" by example, it nowhere defines a third meaning for asterisk (and it defines no meaning, that would not be an operator). Oh, an I nowhere claimed anything is "defined", you made that up. Or as Jonathan Leffler hat put it, in the C standard, * is always "grammar", it's not part of the declaration-specifiers listed (so it is not part of a declaration, thus it must be an operator) – Mecki Oct 11 '17 at 09:25
  • 1
    @Mecki see C11 6.7.6.1/1, the meaning of `*` in declarators is specified. It's a part of the syntax for declaring a pointer (for example, `int * a;` declares `a` having type "pointer to `int`") – M.M Oct 12 '17 at 00:16
  • 1
    The use of `*` as an operator is defined by C11 6.5.3. The code `int *a;` does not match the grammar specification for a unary-expression, therefore the `*` symbol is not an operator there. In fact, `int *a;` is a declaration. Declarations and expressions are different. Declarations are covered by 6.7, expressions are covered by 6.5. – M.M Oct 12 '17 at 00:18
  • 1
    @M.M 6.7.6.1 only shows the declaration by example, exactly like I said, it gives no **meaning** to `*` (it gives only a meaning to the total expression, not to the `*` within the expression!). It says that "int *a;" declares a pointer, which it does, never claimed otherwise, but without a meaning given to `*`, reading it as *the dereferenced value of `a` is an int* is still totally valid, as that has the same factual meaning. Nothing, really nothing written in 6.7.6.1 would contradict that statement. – Mecki Oct 12 '17 at 12:10
  • 7
    There is no "total expression". `int *a;` is a declaration, not an expression. `a` is not dereferenced by `int *a;`. `a` doesn't even exist yet at the point the `*` is being processed. Do you think `int *a = NULL;` is a bug because it dereferences a null pointer? – M.M Oct 12 '17 at 22:04
45

Because the * in that line binds more closely to the variable than to the type:

int* varA, varB; // This is misleading

As @Lundin points out below, const adds even more subtleties to think about. You can entirely sidestep this by declaring one variable per line, which is never ambiguous:

int* varA;
int varB;

The balance between clear code and concise code is hard to strike — a dozen redundant lines of int a; isn't good either. Still, I default to one declaration per line and worry about combining code later.

ojrac
  • 13,231
  • 6
  • 37
  • 39
  • 5
    Well, the misleading first example is in my eyes a design error. If I could, I would remove that way of declaration from C entirely, and made it so both are of type int*. – Adam Bajger May 29 '19 at 12:54
  • 2
    "the * binds more closely to the variable than to the type" This is a naive argument. Consider `int *const a, b;`. Where does the * "bind"? The type of `a` is `int* const`, so how can you say that the * belongs to the variable when it is part of the type itself? – Lundin Jun 04 '19 at 11:09
  • 1
    Specific to the question, or covering all cases: choose one. I'll make a note, but this is another good argument for my last suggestion: one declaration per line reduces the opportunities to mess this up. – ojrac Jun 05 '19 at 14:11
  • If you have that many variables stacked together in one function, maybe is that function doing too much? You should consider splitting up the function body into multiple parts and clean it up before looking into how to compress (and potentially clutter) its declarations in the most concise way available to you. – ljleb Feb 09 '22 at 03:39
21

I'm going to go out on a limb here and say that there is a straight answer to this question, both for variable declarations and for parameter and return types, which is that the asterisk should go next to the name: int *myVariable;. To appreciate why, look at how you declare other types of symbol in C:

int my_function(int arg); for a function;

float my_array[3] for an array.

The general pattern, referred to as declaration follows use, is that the type of a symbol is split up into the part before the name, and the parts around the name, and these parts around the name mimic the syntax you would use to get a value of the type on the left:

int a_return_value = my_function(729);

float an_element = my_array[2];

and: int copy_of_value = *myVariable;.

C++ throws a spanner in the works with references, because the syntax at the point where you use references is identical to that of value types, so you could argue that C++ takes a different approach to C. On the other hand, C++ retains the same behaviour of C in the case of pointers, so references really stand as the odd one out in this respect.

Injektilo
  • 581
  • 3
  • 14
15

A great guru once said "Read it the way of the compiler, you must."

http://www.drdobbs.com/conversationsa-midsummer-nights-madness/184403835

Granted this was on the topic of const placement, but the same rule applies here.

The compiler reads it as:

int (*a);

not as:

(int*) a;

If you get into the habit of placing the star next to the variable, it will make your declarations easier to read. It also avoids eyesores such as:

int* a[10];

-- Edit --

To explain exactly what I mean when I say it's parsed as int (*a), that means that * binds more tightly to a than it does to int, in very much the manner that in the expression 4 + 3 * 7 3 binds more tightly to 7 than it does to 4 due to the higher precedence of *.

With apologies for the ascii art, a synopsis of the A.S.T. for parsing int *a looks roughly like this:

      Declaration
      /         \
     /           \
Declaration-      Init-
Secifiers       Declarator-
    |             List
    |               |
    |              ...
  "int"             |
                Declarator
                /       \
               /        ...
           Pointer        \
              |        Identifier
              |            |
             "*"           |
                          "a"

As is clearly shown, * binds more tightly to a since their common ancestor is Declarator, while you need to go all the way up the tree to Declaration to find a common ancestor that involves the int.

dgnuff
  • 3,195
  • 2
  • 18
  • 32
  • 2
    No, the compiler most definitely reads the type as `(int*) a`. – Lundin Jun 04 '19 at 06:30
  • @Lundin This is the great misunderstanding that most modern C++ programmers have. Parsing a variable declaration goes something like this. Step 1. Read the first token, that becomes the "base type" of the declaration. `int` in this case. Step 2. Read a declaration, including any type decorations. `*a` in this case. Step 3 Read next character. If comma, consume it and go back to step 2. If semicolon stop. If anything else throw a syntax error. ... – dgnuff Jun 05 '19 at 23:37
  • 1
    @Lundin ... If the parser read it the way you are suggesting, then we'd be able to write `int* a, b;` and get a pair of pointers. The point I'm making is that the `*` binds to the variable and is parsed with it, not with the type to form the "base type" of the declaration. That's also part of the reason that typedefs were introduced to allow `typedef int *iptr;` `iptr a, b;` create a couple of pointers. By using a typedef you *can* bind the `*` to the `int`. – dgnuff Jun 05 '19 at 23:41
  • No, the compiler will most likely read it as the formal syntax indicates (see my answer for quotes). That is: the declarator-specifier separate and the init-declarator-list separate, where the latter is split up in items of pointer/direct-declarator pairs. Then when determining the actual type of the variable, the declarator-specifier and the pointer together forms the type. – Lundin Jun 10 '19 at 06:28
  • @Lundin Yes, the compiler reads it as the syntax contaned in the standard dictates. Which can be find as BNF in several places on the web. Or as shown above in the ascii art I added. The point I'm trying to make is that `Declarator` (part of the `Init-Declarator-List`) consumes both the `*` and the variable name. It is on that basis that I state it's parsed as `int (*a)` ... – dgnuff Jun 10 '19 at 07:09
  • 1
    ... Certainly, the compiler "combines" the base type from the `Declaration-Specifier` with the "decorations" in the `Declarator` to arrive at the final type for each variable. However it doesn't "move" the decorations to the Declaration specifier otherwise `int a[10], b;` would produce completely ridiculous results, It parses `int *a, b[10];` as `int` `*a` `,` `b[10]` `;`. There's no other way to describe it that makes sense. – dgnuff Jun 10 '19 at 07:11
  • 3
    Yeah well, the important part here isn't really the syntax or order of compiler parsing, but that the type of `int*a` is in the end read by the compiler as: "`a` has type `int*`". That was what I mean with my original comment. – Lundin Jun 10 '19 at 08:13
  • @Lundin You could just as easily say that `a` has type `*int`, in fact I'd argue that's clearer, since nowhere in the standard does anything like `int*` exist. – SilverbackNet Mar 15 '21 at 23:00
  • Coming here over lately I think `int* a[10]` requires more explanation (`int (*(a[10]))`) as without that might easily be interpreted as (the totally different) `int (*a)[10]` (maybe explain that one as well?). – Aconcagua Feb 04 '22 at 13:06
  • About how to read the type: I personally prefer *'if I dereference `a` then I get type `int` which means that `a` must be a pointer to'*, in other words/in short: `*a` has type `int` – which would then allow to read `b[10]` as *'`b` is an array of which the elements have type `int`'*. Especially this reading would allow to explain multiple variables declared in the same expression. – Aconcagua Feb 04 '22 at 13:11
13

People who prefer int* x; are trying to force their code into a fictional world where the type is on the left and the identifier (name) is on the right.

I say "fictional" because:

In C and C++, in the general case, the declared identifier is surrounded by the type information.

That may sound crazy, but you know it to be true. Here are some examples:

  • int main(int argc, char *argv[]) means "main is a function that takes an int and an array of pointers to char and returns an int." In other words, most of the type information is on the right. Some people think function declarations don't count because they're somehow "special." OK, let's try a variable.

  • void (*fn)(int) means fn is a pointer to a function that takes an int and returns nothing.

  • int a[10] declares 'a' as an array of 10 ints.

  • pixel bitmap[height][width].

  • Clearly, I've cherry-picked examples that have a lot of type info on the right to make my point. There are lots of declarations where most--if not all--of the type is on the left, like struct { int x; int y; } center.

This declaration syntax grew out of K&R's desire to have declarations reflect the usage. Reading simple declarations is intuitive, and reading more complex ones can be mastered by learning the right-left-right rule (sometimes call the spiral rule or just the right-left rule).

C is simple enough that many C programmers embrace this style and write simple declarations as int *p.

In C++, the syntax got a little more complex (with classes, references, templates, enum classes), and, as a reaction to that complexity, you'll see more effort into separating the type from the identifier in many declarations. In other words, you might see see more of int* p-style declarations if you check out a large swath of C++ code.

In either language, you can always have the type on the left side of variable declarations by (1) never declaring multiple variables in the same statement, and (2) making use of typedefs (or alias declarations, which, ironically, put the alias identifiers to the left of types). For example:

typedef int array_of_10_ints[10];
array_of_10_ints a;
Adrian McCarthy
  • 45,555
  • 16
  • 123
  • 175
  • Small question, why can't void (*fn)(int) mean "fn is a function that accepts an int, and returns (void *) ? – a3y3 Oct 03 '19 at 12:07
  • 2
    @a3y3: Because the parentheses in `(*fn)` keep the pointer associated with `fn` rather than the return type. – Adrian McCarthy Oct 06 '19 at 17:18
  • Got it. I think it's important enough to be added in your answer, I'll suggest an edit soon. – a3y3 Oct 06 '19 at 22:57
  • 3
    I think that clutters the answer without adding much value. This is simply the syntax of the language. Most people asking about why the syntax is this way probably already know the rules. Anyone else who's confused on this point can see the clarification in these comments. – Adrian McCarthy Oct 08 '19 at 23:41
  • 3
    "People who prefer `int* x;` are trying to force their code into a fictional world where the type is on the left and the identifier (name) is on the right." People like Bjarne Stroustrup? https://www.stroustrup.com/bs_faq2.html#whitespace – Pulseczar Apr 29 '21 at 01:20
  • @Pulseczar: Yes, Stroustrup is a member of the club that prefers to fight the language's syntax to pretend that the type information is always on the left. His explanation that you linked to conveniently ignores arrays and function pointers where type information surrounds the identifier. And now we have even more esoteric cases (like functions with trailing return types, lambdas whose types cannot be expressed in source code and must instead be captured with auto, and possibly structured bindings), I'm not even sure my final claim holds. – Adrian McCarthy Apr 29 '21 at 04:22
  • @Adrian McCarthy: You can do only so much to make up for design flaws in C (compiler should expect type information to be together) and still maintain backwards compatibility with all C programs. They got it right with Java, with array declaration, but they had no constraint of caring about compatibility with C. – Pulseczar May 01 '21 at 22:23
  • @pulseczar: On programmer's design flaw is another programmer's feature. – Adrian McCarthy May 01 '21 at 23:33
  • 1
    @Adrian McCarthy: The word, "feature", in the context of software and products, is usually reserved for positive traits. Maybe there are good reasons for C to split up type information, but I can't think of any. Maybe it just made writing the C compiler a lot easier somehow. – Pulseczar May 02 '21 at 02:26
  • @Pulseczar: My comment was a somewhat sarcastic paraphrasing of a common aphorism about the distinction between bugs and features (in the context of software) depending largely on one's point of view. C's declaration syntax was an intentional choice intended to make declarations similar to usage. K&R considered this to be a (positive) feature, not a design flaw. – Adrian McCarthy Jan 19 '22 at 16:58
  • @Adrian McCarthy: Other than multiplication, `*` functions as a pointer dereference, in C. Basically everyone writes that with the operator right next to the variable name (`*var`), to avoid looking like multiplication. Putting the `*` next to the variable in a declaration of a pointer makes it less distinguishable from a dereference. Also, putting type information together means you don't have to look at the variable name to get all the information about the variable's type. That's why I consider it a flaw (as well as `var[]`). Let's group like information together. That is more efficient. – Pulseczar Jan 20 '22 at 17:34
  • @Pulseczar: You're making my point: What you view as a design flaw (bug) was an intentional choice (feature) in the eyes of the language designers. The flaw/feature here is "declaration follows usage," and it's discussed in K&R 2ed in chapter 5, page 94, where they mention how it applies to function declarations as well as pointers. If you consider it a design flaw, fine. But C++ adopted C's syntax and it's not going to change ("get fixed") because of the commitment to backward compatibility. Pretending that the type information is only on the left is denial. – Adrian McCarthy Jan 21 '22 at 18:48
  • I'm not pretending type information is only on the left. I've demonstrated my understanding that it's, unfortunately, not (by declaring it a flaw in C), and demonstrated my understanding that C++ keeps it that way to maintain backward compatibility. I'm saying the C compiler should have been originally written with all type information together. I'm also saying that when we can put all of the type information on the left (e.g., `int* x;`), we should. I don't see anything on page 94, or the surrounding pages, that justifies splitting up type information (splitting up like information). – Pulseczar Jan 24 '22 at 16:21
12

That's just a matter of preference.

When you read the code, distinguishing between variables and pointers is easier in the second case, but it may lead to confusion when you are putting both variables and pointers of a common type in a single line (which itself is often discouraged by project guidelines, because decreases readability).

I prefer to declare pointers with their corresponding sign next to type name, e.g.

int* pMyPointer;
macbirdie
  • 16,086
  • 6
  • 47
  • 54
11

A lot of the arguments in this topic are plain subjective and the argument about "the star binds to the variable name" is naive. Here's a few arguments that aren't just opinions:


The forgotten pointer type qualifiers

Formally, the "star" neither belongs to the type nor to the variable name, it is part of its own grammatical item named pointer. The formal C syntax (ISO 9899:2018) is:

(6.7) declaration:
declaration-specifiers init-declarator-listopt ;

Where declaration-specifiers contains the type (and storage), and the init-declarator-list contains the pointer and the variable name. Which we see if we dissect this declarator list syntax further:

(6.7.6) declarator:
pointeropt direct-declarator
...
(6.7.6) pointer:
* type-qualifier-listopt
* type-qualifier-listopt pointer

Where a declarator is the whole declaration, a direct-declarator is the identifier (variable name), and a pointer is the star followed by an optional type qualifier list belonging to the pointer itself.

What makes the various style arguments about "the star belongs to the variable" inconsistent, is that they have forgotten about these pointer type qualifiers. int* const x, int *const x or int*const x?

Consider int *const a, b;, what are the types of a and b? Not so obvious that "the star belongs to the variable" any longer. Rather, one would start to ponder where the const belongs to.

You can definitely make a sound argument that the star belongs to the pointer type qualifier, but not much beyond that.

The type qualifier list for the pointer can cause problems for those using the int *a style. Those who use pointers inside a typedef (which we shouldn't, very bad practice!) and think "the star belongs to the variable name" tend to write this very subtle bug:

    /*** bad code, don't do this ***/
    typedef int *bad_idea_t; 
    ...
    void func (const bad_idea_t *foo);

This compiles cleanly. Now you might think the code is made const correct. Not so! This code is accidentally a faked const correctness.

The type of foo is actually int*const* - the outer most pointer was made read-only, not the pointed at data. So inside this function we can do **foo = n; and it will change the variable value in the caller.

This is because in the expression const bad_idea_t *foo, the * does not belong to the variable name here! In pseudo code, this parameter declaration is to be read as const (bad_idea_t *) foo and not as (const bad_idea_t) *foo. The star belongs to the hidden pointer type in this case - the type is a pointer and a const-qualified pointer is written as *const.

But then the root of the problem in the above example is the practice of hiding pointers behind a typedef and not the * style.


Regarding declaration of multiple variables on a single line

Declaring multiple variables on a single line is widely recognized as bad practice1). CERT-C sums it up nicely as:

DCL04-C. Do not declare more than one variable per declaration

Just reading the English, then common sense agrees that a declaration should be one declaration.

And it doesn't matter if the variables are pointers or not. Declaring each variable on a single line makes the code clearer in almost every case.

So the argument about the programmer getting confused over int* a, b is bad. The root of the problem is the use of multiple declarators, not the placement of the *. Regardless of style, you should be writing this instead:

    int* a; // or int *a
    int b;

Another sound but subjective argument would be that given int* a the type of a is without question int* and so the star belongs with the type qualifier.

But basically my conclusion is that many of the arguments posted here are just subjective and naive. You can't really make a valid argument for either style - it is truly a matter of subjective personal preference.


1) CERT-C DCL04-C.

Community
  • 1
  • 1
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Rather amusingly, if you read that article I linked, there's a short section on the topic of `typedef int *bad_idea_t;` `void func(const bad_idea_t bar);` As the great prophet Dan Saks teaches "If you always place the `const` as far to the right as you can, without changing the semantic meaning" this completely ceases to be an issue. It also makes your `const` declarations more consistent to read. "Everything to the right of the word const is that which is const, everything to the left is its type." This will apply to all consts in a declaration. Try it with `int const * * const x;` – dgnuff Jun 06 '19 at 17:24
  • The question is not about whether one should write the asterisk here or there. The question is why c programmers (mostly) write the asterisk to the variable, which they do. – johannes_lalala Jan 19 '22 at 00:19
  • .. if you're put in a situation where you just have to do it alike, it helps to have reasoning for it. – johannes_lalala Jan 19 '22 at 00:26
  • 1
    Even thought this doesn't answer the question exactly, it's still on topic and presents valuable arguments for a more objective point of view. IMO, in the long run this should be the accepted answer, since the style choices of people change over time and should not be justified by harmful syntax features (like declaring multiple variables in a single declaration statement). – ljleb Feb 09 '22 at 03:59
3

Because it makes more sense when you have declarations like:

int *a, *b;
Greg Rogers
  • 35,641
  • 17
  • 67
  • 94
  • 9
    This is literally an example of begging the question. No, it does not make more sense that way. "int* a ,b" could just as well make both of them pointers. – MichaelGG Aug 19 '15 at 21:02
  • 5
    @MichaelGG You've got the tail wagging the dog there. Sure K&R *could* have specified that `int* a, b;` made `b` a pointer to `int`. But they didn't. And with good reason. Under your proposed system what is the type of `b` in the following declaration: `int* a[10], b;`? – dgnuff Jun 04 '18 at 18:18
  • 1
    @dgnuff: We wouldn't just do one thing correctly; we'd do it *all* correctly. `int* a[10], b;` wouldn't be allowed, because `int* a[10];` wouldn't be allowed. Type information would be required to be together, as, for example, this: `int*[10] a;` It would mean: create 10 pointers to `int`s as an array. Type information is together. Then, you could add a `b` variable to that (`int*[10] a, b;`), that would have the same type (10 pointers to `int`s as an array). – Pulseczar Jan 20 '22 at 17:44
1

For declaring multiple pointers in one line, I prefer int* a, * b; which more intuitively declares "a" as a pointer to an integer, and doesn't mix styles when likewise declaring "b." Like someone said, I wouldn't declare two different types in the same statement anyway.

heyitsluke
  • 35
  • 1
1

When you initialize and assign a variable in one statement, e.g.

int *a = xyz;

you assign the value of xyz to a, not to *a. This makes

int* a = xyz;

a more consistent notation.

Urquhart
  • 129
  • 10