A clarification please

M

mdh

FAQ 1.7 shows that, amongst other things,

int i = 0;

is a definition.

Page 128 of K&R say:

"A struct declaration defines a type. The right brace that terminates
the list of members may be followed by a list of variables, just as
for any basic type. That is,

struct {.....} x, y, z:

is syntactically analogous to

int x, y, z;

in the sense that each statement declares x, y, and z to be variables
of the named type **and causes space to be set aside for them**. {My
emphasis}

My understanding was that a definition causes space to be set aside,
( eg int i = 0) but not a declaration ( eg int i) and the x, y, and z
in the above example. How can these two ideas be reconciled?

Thanks as usual.
 
J

jameskuyper

mdh said:
FAQ 1.7 shows that, amongst other things,

int i = 0;

is a definition.

Page 128 of K&R say:

"A struct declaration defines a type. The right brace that terminates
the list of members may be followed by a list of variables, just as
for any basic type. That is,

struct {.....} x, y, z:

is syntactically analogous to

int x, y, z;

in the sense that each statement declares x, y, and z to be variables
of the named type **and causes space to be set aside for them**. {My
emphasis}

My understanding was that a definition causes space to be set aside,
( eg int i = 0) but not a declaration ( eg int i) and the x, y, and z
in the above example. How can these two ideas be reconciled?

By noting that your concept of what a definition is isn't quite right.

A declaration that explicitly initializes the value of a variable is
always a definition. The same is true of a file scope declaration
using the keyword 'static', or any other declaration that does not use
the keyword 'extern'. That last case covers 'int i;' when it occurs at
block scope.

However, all other variable declarations are considered "tentative",
including "int i;" if it occurs at file scope, and that's where it
gets tricky. If a tentative definition is followed by a later
declaration of the same variable name in the same scope that includes
an initializer or uses the keyword 'static', the tentative definition
becomes a real definition. If, by the end of the translation unit,
there are no non-tentative definitions of a variable, then the
tentative definition becomes a real one, unless it was declared
'extern', in which case it becomes a declaration of a variable who's
actual definition lies elsewhere.
 
B

Barry Schwarz

FAQ 1.7 shows that, amongst other things,

int i = 0;

is a definition.

Page 128 of K&R say:

"A struct declaration defines a type. The right brace that terminates
the list of members may be followed by a list of variables, just as
for any basic type. That is,

struct {.....} x, y, z:

is syntactically analogous to

int x, y, z;

in the sense that each statement declares x, y, and z to be variables
of the named type **and causes space to be set aside for them**. {My
emphasis}

My understanding was that a definition causes space to be set aside,
( eg int i = 0) but not a declaration ( eg int i) and the x, y, and z
in the above example. How can these two ideas be reconciled?

By correcting your understanding.

int i; is a definition. It causes space to be set aside (in some
implementation specific sense of the phrase) for object i. If it
didn't, code such as i = j+k; would have no place to store the result.

extern int i; is a declaration. It promises that i is in fact defined
somewhere else and the linker will be able to resolve its location.

struct t {...}; is a declaration. It doesn't define an object. It
does "define" a new type. (I prefer to say it declares the type but
it's hard to argue with K&R.) In any event, defining a type is
different than defining an object or function. struct t {...} x; is a
definition. It defines the object x and reserves space for it.

All of which proves that the word "define" and words derived from it
mean different things when used to describe the creation of objects or
used to describe other aspects of the language.

This is not that unusual. The word "token" means different things
when talking about the preprocessor, language syntax, or the use of
the standard function strtok. Context is important when trying to
decide what things mean.
 
M

mdh

By noting that your concept of what a definition is isn't quite right.

A declaration that explicitly initializes the value of a variable is
always a definition. The same is true of a file scope declaration
using the keyword 'static', or any other declaration that does not use
the keyword 'extern'. That last case covers 'int i;' when it occurs at
block scope.

However, all other variable declarations are considered "tentative",
including "int i;" if it occurs at file scope, and that's where it
gets tricky. If a tentative definition is  followed by a later
declaration of the same variable name in the same scope that includes
an initializer or uses the keyword 'static', the tentative definition
becomes a real definition. If, by the end of the translation unit,
there are no non-tentative definitions of a variable, then the
tentative definition becomes a real one, unless it was declared
'extern', in which case it becomes a declaration of a variable who's
actual definition lies elsewhere.

My head is spinning!! :)

Thank you for that explanation.
 
M

mdh

t declares x, y, and z to be variables
How can these two ideas be reconciled?

By correcting your understanding.


That, sadly, has been happening a lot lately!! :)
int i; is a definition.  It causes space to be set aside (in some
implementation specific sense of the phrase) for object i.  If it
didn't, code such as i = j+k; would have no place to store the result.

extern int i; is a declaration.  It promises that i is in fact defined
somewhere else and the linker will be able to resolve its location.

struct t {...}; is a declaration.  It doesn't define an object.  It
does "define" a new type.  (I prefer to say it declares the type but
it's hard to argue with K&R.)  In any event, defining a type is
different than defining an object or function.  struct t {...} x; is a
definition.  It defines the object x and reserves space for it.  

All of which proves that the word "define" and words derived from it
mean different things when used to describe the creation of objects or
used to describe other aspects of the language.

This is not that unusual.  The word "token" means different things
when talking about the preprocessor, language syntax, or the use of
the standard function strtok.  Context is important when trying to
decide what things mean.


thank you Barry. That does clarify it.
 
M

mdh

I think your take was based on a possible misunderstanding of what
constitutes a definition. It is not syntactically necessary for there to
be an initialiser in order for a declaration to become a definition.


Thanks Richard.
 
M

mdh

mdh said:


All definitions are also declarations. Not all declarations are
definitions, however.

struct foo x, y, z; is a definition (and of course a declaration, but the
important point here is that it is a definition). It defines (reserves
storage for) x, y, and z, which are all objects of type struct foo.



May I pursue this for just a moment. In another thread, I got a very
extensive ( and appreciated) answer to the question of "re-declaring
a struct" from BB.

Re-declaring it won't work. The standard says this:
"Moreover, two structure, union, or enumerated types declared in
separate translation units are compatible if their tags and
members
satisfy the following requirements: ..."
[you can stop reading here if you like]
"... If one is declared with a tag, the other shall be declared
with the same tag. If both are complete types, then the following
additional requirements apply: there shall be a one-to-one
correspondence between their members such that each pair of
corresponding members are declared with compatible types, and such
that if one member of a corresponding pair is declared with a
name,
the other member is declared with the same name. For two
structures, corresponding members shall be declared in the same
order. For two structures or unions, corresponding bit-fields
shall
have the same widths."
The key part is "declared in separate translation units". Two
structs, declared in the same translation unit, even in separate
scopes, can't ever be compatible -- no matter how similar they look.
<<<<<



So, I made up this little bit of code.

#include <stdio.h>

int main (int argc, const char * argv[]) {


int foo (int); /* first declaration of foo */

int x = foo (7);
int foo (int); /* 2nd declaration of foo */
/* no error */


struct name { /* first declaration of struct */
int x;
};

struct name { /*error : Redefinition of struct name */
int x;
};

struct name p = {
20
};

return 0;
}


int foo (int x){
return 9;
}


From Ben's note, I expected to get a re-declaration error, (for the
struct) not a redefinition error. Moreover, if the declaration is
placed at block level, and a second declaration is placed at file
level, there is not error generated. ( From my understanding of
declaration of functions, I did not expect an error for foo, and got
none. ) Any insight is appreciated. Thanks in advance.
 
M

mdh

mdh said:




I think the reason you're confused may be that you are conflating two
different meanings of the word "definition". The meaning we've been
discussing recently is the definition of an identifier to describe an
object. But:

struct name { int x; };


doesn't define an object - it defines a *type*. Within a given scope, you
can only define a type once.

Aha...that's what I have been missing. Thank you Richard.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,139
Latest member
JamaalCald
Top