I initially assumed that this was a habit left over from the days when you had to declare all local variables at the top of the scope. But I've learned not to dismiss so quickly the habits of veteran developers. So, is there a good reason for declaring in one line, and assigning afterwards?

EDIT: Some people are confused about my tagging of this question as both c and c++. So, to clarify, I was interested in the difference between how these will behave in both C and C++. There are a lot of instances where the same code will behave differently in C++ than in C.

EDIT 2: Apologies for the poor wording: I probably shouldn't have used the words declare and define without making clear exactly what I meant by them, since they have very specific meanings in different contexts. I've changed the title to say “assign” instead.

7 Answers
7

C

In C89 all declarations had to be be at the beginning of a scope ({ ... }), but this requirement was dropped quickly (first with compiler extensions and later with the standard).

C++

These examples are not the same. some_type val = something; calls the copy constructor while val = something; calls the default constructor and then the operator= function. This difference is often critical.

Habits

Some people prefer to first declare variables and later define them, in the case they are reformatting their code later with the declarations in one spot and the definition in an other.

About the pointers, some people just have the habit to initialize every pointer to NULL or nullptr, no matter what they do with that pointer.

Great distinction for C++, thanks. What about in plain C?
–
Jonathan SterlingMay 7 '11 at 20:35

11

The fact that MSVC still doesn't support declarations except at the beginning of a block when it's compiling in C mode is the source of endless irritation for me.
–
Michael BurrMay 7 '11 at 22:03

4

@Michael Burr: This is because MSVC doesn't support C99 at all.
–
orlpMay 7 '11 at 22:05

1

"some_type val = something; calls the copy constructor": it may call the copy constructor, but the Standard allows the compiler to elide the default-construction of a tempory, copy construction of val and destruction of the temporary and directly construct val using a some_type constructor taking something as sole argument. This is a very interesting and unusual edge case in C++... it means there's a presumption about the semantic meaning of these operations.
–
TonyMay 9 '11 at 9:15

1

@Aerovistae: for built-in types they are the same, but the same can not always be said for user-defined types.
–
orlpOct 11 '12 at 18:48

You have tagged your question C and C++ at the same time, while the answer is significantly different in these languages.

Firstly, the wording of the title of your question is incorrect (or, more precisely, irrelevant to the question itself). In both of your examples the variable is declared and defined simultaneously, in one line. The difference between your examples is that in the first one the variables are either left uninitialized or initialized with a dummy value and then it is assigned a meaningful value later. In the second example the variables are initialized right away.

Secondly, in C++ language, as @nightcracker noted in his answer these two constructs are semantically different. The first one relies on initialization while the second one - on assignment. In C++ these operations are overloadable and therefore can potentially lead to different results (although one can note that producing non-equivalent overloads of initialization and assignment is not a good idea).

In the original standard C language (C89/90) it is illegal to declare variables in the middle of the block, which is why you might see variables declared uninitialized (or initialized with dummy values) at the beginning of the block and then assigned meaningful values later, when those meaningful values become available.

In C99 language it is OK to declare variables in the middle of the block (just like in C++), which means that the first approach is only needed in some specific situations when the initializer is not known at the point of declaration. (This applies to C++ as well).

@Jonathan Sterling: I read your examples. You probably need to brush up on the standard terminology of C and C++ languages. Specifically, on the terms declaration and definition, which have specific meanings in these languages. I'll repeat it again: in both of your examples the variables are declared and defined in one line. In C/C++ the line some_type val; immediately declares and defines the variable val. This is what I meant in my answer.
–
AndreyTMay 7 '11 at 20:53

1

I see what you mean there. You're definitely right about declare and define being rather meaningless the way I used them. I hope you accept my apologies for the poor wording, and poorly-thought-out comment.
–
Jonathan SterlingMay 7 '11 at 20:55

1

In any other context declare would be the right word, but since declare is a well-defined concept, with consequences, in C and C++ you can not use it as loosely as you could in other contexts.
–
orlpMay 7 '11 at 21:15

1

@ybungalobill: You are wrong. Declaration and definition in C/C++ is not mutually exclusive concepts. Actually, definition is just a specific form of declaration. Every definition is a declaration at the same time (with few exceptions). There are defining declarations (i.e. definitions) and non-defining declarations. Moreover, normally the therm declaration is used all the time (even if it is a definition), except for the contexts when the distinction between the two is critical.
–
AndreyTMay 7 '11 at 21:52

1

@Jonathan Sterling: Declare is the right word, even if the declaration is a definition at the same time. This is the accepted practice in C/C++ standard language: unless you care to distinguish between definitions and non-defining declarations, you just use the term declaration. In the context of your question, the distinction does not matter, so you can just use the term declaration. The wording in your current title is perfectly fine.
–
AndreyTMay 7 '11 at 21:55

The other answers are pretty good. There's some history around this in C. In C++ there's the difference between a constructor and an assignment operator.

I'm surprised no one mentions the additional point: keeping declarations separate from use of a variable can sometimes be a lot more readable.

Visually speaking, when reading code, the more mundane artifacts, such as the types and names of variables, are not what jump out at you. It's the statements that you're usually most interested in, spend most time staring at, and so there's a tendency to glance over the rest.

If I have some types, names, and assignment all going on in the same tight space, it's a bit of information overload. Further, it means that something important is going on in the space that I usually glance over.

It may seem a bit counter-intuitive to say, but this is one instance where making your source take up more vertical space can make it better. I see this as akin to why you shouldn't write jam-packed lines which do crazy amounts of pointer arithmetic and assignment in a tight vertical space -- just because the language lets you get away with such things doesn't mean you should do it all the time. :-)

In C, this was the standard practice because variables had to be declared at the start of the function, unlike in C++, where it could be declared anywhere in the function body to be used thereafter. Pointers were set to 0 or NULL, because it just made sure that the pointer pointed to no garbage. Otherwise, there's no significant advantage that I can think of, which compels anyone to do like that.

Pros for localising variable definitions and their meaningful initialisation:

if variables are habitually assigned a meaningful value when they first appear in the code (another perspective on the same thing: you delay their appearance until a meaningful value is avaialable) then there's no chance of them accidentally being used with a meaningless or uninitialised value (which can easily happen is some initialisation is accidentally bypassed due to conditional statements, short-circuit evaluation, exceptions etc.)

can be more efficient

avoids overheads of setting initial value (default construction or initialisation to some sentinel value like NULL)

operator= can sometimes be less efficient and require a temporary object

I wish more languages would distinguish the case where code declares and sets the value of a variable which would never be written elsewhere, though new variables could use the same name [i.e. where behavior would be the same whether the later statements used the same variable or a different one], from those where code creates a variable that must be writable in multiple places. While both use cases will execute the same way, knowing when variables may change is very helpful when trying to track down bugs.
–
supercatApr 28 '14 at 22:50