tags:

views:

1514

answers:

9

As title says, the meaning of both eludes me.

+5  A: 

From wiki.answers.com:

The term declaration means (in C) that you are telling the compiler about type, size and in case of function declaration, type and size of its parameters of any variable, or user defined type or function in your program. No space is reserved in memory for any variable in case of declaration. However compiler knows how much space to reserve in case a variable of this type is created.

for example, following are all declarations: extern int a; struct _tagExample { int a; int b; }; int myFunc (int a, int b);

Definition on the other hand means that in additions to all the things that declaration does, space is also reserved in memory. You can say "DEFINITION = DECLARATION + SPACE RESERVATION" following are examples of definition: int a; int b = 0; int myFunc (int a, int b) { return a + b; } struct _tagExample example;

see Answers.

Marcin Gil
This, too, is wrong (although much closer than the others): `struct foo {};` is a __definition__, not a declaration. A declaration of `foo` would be `struct foo;`. From that, the compiler doesn't know how much space to reserve for `foo` objects.
sbi
sbi, my answer reflects what you are saying. in your example, you define a foo as an empty structure. I fail to understand how our examples are technically different.
San Jacinto
@Marcin: sbi is saying that "compiler knows how much space to reserve in case a variable of this type is created" is not always true. `struct foo;` is a declaration, but it does not tell the compiler the size of foo. I'd add that `struct _tagExample { int a; int b; };` is a definition. So in this context it is misleading to call it a declaration. Of course it is one, since all definitions are declarations, but you seem to be suggesting that it is not a definition. It is a definition, of _tagExample.
Steve Jessop
Just quoted "Answers" wiki.
Marcin Gil
@Marcin Gil: Which means that "Answers" wiki is not always accurate. I have to downvote for misinformation here.
David Thornley
So we have an answer copied straight from MSDN (adatapost's) and one from answers.com and both are misleading or even plain wrong. What do we learn from this?
sbi
We learn that what adatapost quoted is true but does not (IMO) really answer the question. What Marcin quoted is false. Quoting the standards is true and answers the question, but is very difficult to make head or tail of.
Steve Jessop
@onebyone: A _very_ nice summary indeed! (I, however, had reinforced what I learned as a student and later tried to hammer into _my_ students: Copying without thinking might lead to a disaster. `:^>`)
sbi
@David Thornley - not a problem :) This is what this site is about. *We* select and verify info.
Marcin Gil
It should be noted that `struct foo { int a; };` in C is not a definition. C doesn't know struct definitions. In reverse, a typedef is a definition in C.
Johannes Schaub - litb
+10  A: 

Declaration

Declarations tell the compiler that a program element or name exists. A declaration introduces one or more names into a program. Declarations can occur more than once in a program. Therefore, classes, structures, enumerated types, and other user-defined types can be declared for each compilation unit.

Definition

Definitions specify what code or data the name describes. A name must be declared before it can be used.

adatapost
Um, isn't it that you can even _define_ classes and enums in each compilation unit? At least I put class _definitions_ into my headers and include them all over. Er, `class foo {};` _is_ a class _definition_, isn't it?
sbi
Yes. However, "class foo;" is a declaration. It tells the compiler that foo is a class. "class foo {};" is a definition. It tells the compiler exactly what sort of class foo is.
David Thornley
@David: Right. And since we all put class and enum _definitions_ into our headers files, it's class and enum _definitions_, not declarations, that can be repeated for each compilation unit. That makes adatapost's answer, um, _misleading_.
sbi
The exception are class member names which may be used before they're declared.
Johannes Schaub - litb
@litb: I don't think that's true: `class blah { foo bar(); typedef int foo; };` gives a compile-time error. What you mean is that member function _definitions_ are, even when they are defined _within_ the class' definition, parsed as if they were defined right _behind_ the class' definition.
sbi
Yeah, that's what i meant. So you can do the following: struct foo { void b() { f(); } void f(); }, f is visible even though not declared yet. The following works too: struct foo { void b(int = bar()); typedef int bar; };. It's visible before its declaration in "all function bodies, default arguments, constructor ctor-initializers". Not in the return type :(
Johannes Schaub - litb
@litb: It isn't visible before it's declaration, it's only that the _use_ of the identifier is moved behind the declaration. Yeah, I know, the effect is the same for many cases. But not for all cases, which is why I think we should use the precise explanation. -- Oops, wait. It is visible in default arguments? Well, that surely wreaks havoc with my understanding. Dammit! <pouts>
sbi
+29  A: 

A declaration introduces an identifier and describes its type, be it a type, object, or function. A declaration is what the compiler needs to accept references to that identifier. These are declarations:

extern int bar;
extern int g(int, int);
double f(int, double); // extern can be omitted for function declarations
class foo; // no extern allowed for class declarations

A definition actually instantiates/implements this identifier. It's what the linker needs in order to link references to those entities. These are definitions corresponding to the above declarations:

int bar;
int g(int lhs, int rhs) {return lhs*rhs;}
double f(int i, double d) {return i+d;}
class foo {};

A definition can be used in the place of a declaration.

An identifier can be declared as often as you want. Thus, the following is legal in C and C++:

double f(int, double);
double f(int, double);
extern double f(int, double); // the same as the two above
extern double f(int, double);

However, it must be defined exactly once. If you forget to define something that's been declared and referenced somewhere, then the linker doesn't know what to link references to and complains about a missing symbols. If you define something more than once, then the linker doesn't know which of the definitions to link references to and complains about duplicated symbols.


Since the debate what is a class declaration vs. a class definition in C++ keeps coming up (in answers and comments to other questions) , I'll paste a quote from the C++ standard here.
At 3.1/2, C++03 says:

A declaration is a definition unless it [...] is a class name declaration [...].

3.1/3 then gives a few examples. Amongst them:

[Example: [...]
struct S { int a; int b; }; // defines S, S::a, and S::b
[...]
struct S; // declares S
—end example]

To sum it up: The C++ standard considers struct x; to be a declaration and struct x {}; a definition. (In other words, "forward declaration" is somewhat of a misnomer, since there are no other forms of class declarations in C++.)

Thanks to litb (Johannes Schaub) who dug out the chapter and verse in one of his answers.

sbi
Is that multiple-declaration legal according to the STANDARD, or your compiler, or what? I cannot do that multiple times in the same scope.
San Jacinto
@unknown: either your compiler is broken of you have mis-copied sbi's code. For example, 6.7.2(2) in N1124: "All declarations that refer to the same object or function shall have compatible type;otherwise, the behavior is undefined."
Steve Jessop
@unknown: or possibly it's issuing a warning, which you're promoting to an error.
Steve Jessop
yes, it was a bad compiler. i tried it again on GCC and it workd. hint: don't use imagecraft's c compiler.
San Jacinto
"If you define something more than once, then the linker doesn't know which of the definitions to link references to". Although you can get away with that if the definitions are in different translation units, are equivalent, and and have appropriate modifiers telling the linker it's OK to fold them (principally "inline")
Steve Jessop
@onebyone: Yes, there are exceptions, notably inlined functions that the compiler won't inline for whatever reason. However, I didn't want to add exceptions to the answer if the questioner doesn't know the difference between declaration and definition. I was quite surprised about all the misleading answers (that have since disappeared). I hadn't thought such misconceptions are so wide-spread.
sbi
I would say that "int i;" is also a declaration, and you never actually DEFINE an int variable... but other than that, +1
Brian Postow
@Brian: "extern int i;" says that i is an int somewhere, don't worry about it. "int i;" means that i is an int, and its address and scope is determined here.
David Thornley
@Brian: You're wrong. `extern int i` is a declaration, since it just introduces/specifies `i`. You can have as many `extern int i` in each compilation unit as you want. `int i`, however, is a definition. It denotes the space for the integer to be in this translation unit and advices the linker to link all references to `i` against this entity. If you have more or less than exactly one of these definitions, the linker will complain.
sbi
@Brian `int i;` in file/global scope or function scope is a definition both in C and C++. In C because it allocates storage, and in C++ because it does not have the extern specifier or a linkage-specification. These amount to the same thing, which is what sbi says: in both cases this declaration specifies the object to which all references to "i" in that scope must be linked.
Steve Jessop
@unknown, beware you cannot redeclare members in *class* scope: `struct A { double f(int, double); double f(int, double); };` invalid, of course. It's allowed elsewhere though. There are some places where you can declare things, but not define, too: `void f() { void g(); }` valid, but not the following: `void f() { void g() { } };`. What is a definition and what a declaration has subtle rules when it comes to templates - beware! +1 for a good answer though.
Johannes Schaub - litb
+3  A: 

From the C++ standard section 3.1:

A declaration introduces names into a translation unit or redeclares names introduced by previous declarations. A declaration specifies the interpretation and attributes of these names.

The next paragraph states (emphasis mine) that a declaration is a definition unless...

... it declares a function without specifying the function’s body

void sqrt(double);  // declares sqrt

... it declares a static member within a class definition

struct X
{
    int a;         // defines a
    static int b;  // declares b
};

... it declares a class name

class Y;

... it contains the extern keyword without an initializer or function body

extern const int i = 0;  // defines i
extern int j;  // declares j
extern "C"
{
    void foo();  // declares foo
}

... or is a typedef or using statement.

typedef long LONG_32;  // declares LONG_32
using namespace std;   // declares std

Now for the big reason why it's important to understand the difference between a declaration and definition: the One Defintion Rule. From section 3.2.1 of the C++ standard:

No translation unit shall contain more than one definition of any variable, function, class type, enumeration type, or template.

Kristo
+3  A: 

From the C99 standard, 6.7(5):

A declaration specifies the interpretation and attributes of a set of identifiers. A definition of an identifier is a declaration for that identifier that:

  • for an object, causes storage to be reserved for that object;
  • for a function, includes the function body;
  • for an enumeration constant or typedef name, is the (only) declaration of the identifier.

From the C++ standard, 3.1(2):

A declaration is a definition unless it declares a function without specifying the function's body, it contains the extern specifier or a linkage-specification and neither an initializer nor a function-body, it declares a static data member in a class declaration, it is a class name declaration, or it is a typedef declaration, a using-declaration, or a using-directive.

Then there are some examples.

So interestingly (or not, but I'm slightly surprised by it), typedef int myint; is a definition in C99, but only a declaration in C++.

Steve Jessop
@onebyone: Regarding the `typedef`, wouldn't that mean that it could be repeated in C++, but not in C99?
sbi
That's what surprised me, and as far as a single translation unit is concerned, yes there is that difference. But clearly a typedef can be repeated in C99 in different translation units. C doesn't have an explicit "one definition rule" like C++, so the rules it does have just allow it. C++ chose to change it to a declaration, but also the one definition rule lists what kinds of things it applies to, and typedefs isn't one of them. So repeats would be allowed in C++ under the ODR as it's worded, even if a typedef was a definition. Seems unnecessarily picky.
Steve Jessop
... but I'd guess that list in the ODR actually lists all the things it's possible to have definitions of. If so, then the list is actually redundant, and is just there to be helpful.
Steve Jessop
What does the std's ODR definition say about class definitions? They _have_ to be repeated.
sbi
I suspect the rationale for it is because a typedef declares just a name, without producing something beyond (like, a type, object or something). So it's just a declaration, much like a using-declaration.
Johannes Schaub - litb
However, note that you *can* have multiple definitions of the same namespace, although it sounds odd: `namespace A { } namespace A { }`
Johannes Schaub - litb
@sbi: ODR says "(1) No translation unit shall contain more than one definition of any ... class type" and "(5) There can be more than one definition of a class type ... in a program provided that each definition appears in a different translation unit" and then some extra requirements which amount to "the definitions are the same".
Steve Jessop
@litb: yep, namespaces aren't mentioned in the first clause of the ODR. Indeed I often use that in header files, where I have groups of functions I close and re-open the namespaces between them, so that each "section" of the header file stands alone.
Steve Jessop
@onebyone: I always thought ODR deals with definitions _across_ translation units. I'm surprised it's limited to TUs.
sbi
@sbi: it deal with both. Clause 1 is about what can't be duplicated in a single translation unit. Clause 5 lists some things which can be duplicated in the program provided they're in different units. There are other wondrous clauses too large to fit in this margin^Hcomment.
Steve Jessop
@onebyone: I tried to dig through the Holy Paper several times, but my understanding of English seems to simply lack too much in order to understand standardeze. <sigh> But then again, maybe I'm just not the kind of person who reads legaleze, not matter what language it comes in...
sbi
@sbi: I've certainly never read the standard cover-to-cover, but the index is pretty good :-)
Steve Jessop
+1  A: 

Couldnt you state in the most general terms possible, that a declaration is an identifier in which no storage is allocated and a definition actually allocates storage from a declared identifier?

One interesting thought - a template cannot allocate storage until the class or function is linked with the type information. So is the template identifier a declaration or definition? It should be a declaration since no storage is allocated, and you are simply 'prototyping' the template class or function.

Phil
Your definition isn't per se wrong, but "storage definition" always seems awkward when it comes to function definitions. Regarding templates: This `template<class T> struct foo;` is a template _declaration_, and so is this `template<class T> void f();`. Template definitions mirror class/function definitions in the same way. (Note that a _template name_ is not a _type_ or _function name_. One place where you can see this is when you cannot pass a template as another template's type parameter. If you want to pass templates instead of types, you need template template parameters.)
sbi
Agreed that 'storage definition' is awkward, especially regarding function definitions. The declaration is int foo() and definition is int foo() {//some code here..}. I usually need to wrap my small brain with concepts I am familiar - 'storage' is one such way to keep it straight to me at least... :)
Phil
+3  A: 

There are interesting edge cases in C++ (some of them in C too). Consider

T t;

That can be a definition or a declaration, depending on what type T is:

typedef void T();
T t; // declaration of function "t"

struct X { 
  T t; // declaration of function "t".
};

typedef int T;
T t; // definition of object "t".

In C++, when using templates, there is another edge case.

template <typename T>
struct X { 
  static int member; // declaration
};

template<typename T>
int X<T>::member; // definition

template<>
int X<bool>::member; // declaration!

The last declaration was not a definition. It's the declaration of an explicit specialization of the static member of X<bool>. It tells the compiler: "If it comes to instantiating X<bool>::member, then don't instantiate the definition of the member from the primary template, but use the definition found elsewhere". To make it a definition, you have to supply an initializer

template<>
int X<bool>::member = 1; // definition, belongs into a .cpp file.
Johannes Schaub - litb
+3  A: 

Declaration "Somewhere, there exists a foo".

Definition: "...and here it is!"

plinth
A: 

A declaration introduces a name into the program; a definition provides a unique description of an entity (e.g. type, instance, and function). Declarations can be repeated in a given scope, it introduces a name in a given scope. There must be exactly one definition of every object, function or class used in a C++ program. A declaration is a definition unless:

* it declares a function without specifying its body,
* it contains an extern specifier and no initializer or function body,
* it is the declaration of a static class data member without a class definition,
* it is a class name definition,
* it is a typedef declaration.

A definition is a declaration unless:

* it defines a static class data member,
* it defines a non-inline member function.
www
Shruti is a cut and paste demon: http://www.discussweb.com/c-c-programming/3931-declaration-definition-c.html
Will