A question about ifndef

Q

QQ

I am reading a book. It introduces ifndef as the following:
--------------------------------------------------------------------------------------
Look at the following code:
#ifndef _CONST_H_INCLUDED_
/* define constants */
#define _CONST_H_INCLUDED_
#endif /* _CONST_H_INCLUDED_ */

When const.h is included, it defines the symbol _CONST_H_INCLUDED_. If
that symbol is already defined (because the file was included earlier),
the #ifndef conditional hides all defines so they don't cause
trouble.
--------------------------------------------------------------------------------------

I don't quite understand why we need to define a symbol in this way.
What does it tell?

Anyone can explain to me?

Thanks a lot!
 
D

Default User

QQ said:
I am reading a book. It introduces ifndef as the following:
----------------------------------------------------------------------
---------------- Look at the following code:
#ifndef _CONST_H_INCLUDED_
/* define constants */
#define _CONST_H_INCLUDED_
#endif /* _CONST_H_INCLUDED_ */

When const.h is included, it defines the symbol _CONST_H_INCLUDED_. If
that symbol is already defined (because the file was included
earlier), the #ifndef conditional hides all defines so they don't
cause trouble.
----------------------------------------------------------------------

It prevents the declarations from the header being included more than
once in the same translation unit.



Brian
 
W

Walter Roberson

I am reading a book. It introduces ifndef as the following:
Look at the following code:
#ifndef _CONST_H_INCLUDED_
/* define constants */
#define _CONST_H_INCLUDED_
#endif /* _CONST_H_INCLUDED_ */
When const.h is included, it defines the symbol _CONST_H_INCLUDED_. If
that symbol is already defined (because the file was included earlier),
the #ifndef conditional hides all defines so they don't cause
trouble.
I don't quite understand why we need to define a symbol in this way.
What does it tell?

You usually only need to include any given header file once per
translation unit: after that, the macros and types and function
prototypes that it defines are present in the translation unit and
you don't need to include them again later.

But header files usually #include all the header files that they
specifically depend on, so that the header file will be sure that
everything it needs will be present.

This practice -often- leads to instances where a particular header
file gets included, and then later down in the translation unit,
something includes it again. That's usually a big waste of compilation
resources... how many times do you need to #define NULL anyhow?

To avoid that waste, the convention was adopted that headers that
only need to be included once, are configured in such a way that
after the first time they get included, a symbol gets defined, and
then the next time they get included, the header looks and sees that
that symbol is already defined and so knows to skip everything it
would have defined.


Note: I wouldn't do it the way you show; I would change the order
slightly, to

#ifndef _CONST_H_INCLUDED_
#define _CONST_H_INCLUDED_
/* define constants */
#endif /* _CONST_H_INCLUDED_ */

where the symbol gets defined before the rest of the file gets
processed. If -somehow- you managed to end up with a loop of #include
files that got back the original file, then with the order you show,
on the second processing of the file, the protective symbol would
not have been defined yet, so the file would get expanded... possibly
resulting in another loop... But if you define the symbol first,
then on the second processing of the file, it would just gracefully
do nothing and continue processing the calling file, eventually
getting back to the first expansion, at which time the file would
be expanded exactly once.
 
B

Ben Pfaff

This practice -often- leads to instances where a particular header
file gets included, and then later down in the translation unit,
something includes it again. That's usually a big waste of compilation
resources... how many times do you need to #define NULL anyhow?

To avoid that waste, the convention was adopted that headers that
only need to be included once, are configured in such a way that
after the first time they get included, a symbol gets defined, and
then the next time they get included, the header looks and sees that
that symbol is already defined and so knows to skip everything it
would have defined.

It's not just for compilation performance. (If it were, then I'd
probably omit them in my header files, because they're ugly.)
It's also to avoid compilation errors due to redefinitions:
structures, unions, and enumerations (and some other kinds of
entities?) may not be defined more than once.
 
B

Ben Pfaff

QQ said:
#ifndef _CONST_H_INCLUDED_
/* define constants */
#define _CONST_H_INCLUDED_
#endif /* _CONST_H_INCLUDED_ */

Identifiers whose names begin with _ followed by a capital letter
are reserved for all uses.
 
P

pete

Ben said:
It's not just for compilation performance. (If it were, then I'd
probably omit them in my header files, because they're ugly.)
It's also to avoid compilation errors due to redefinitions:
structures, unions, and enumerations (and some other kinds of
entities?) may not be defined more than once.

Object definitions and function definitions
don't belong in header files, do they?

If declarations which are neither object defintions
nor function defintions, are declared twice, what's the harm?
 
F

Flash Gordon

pete said:
Ben Pfaff wrote:


Object definitions and function definitions
don't belong in header files, do they?

Yes, but I'm sure that is not what Ben was referring to.
If declarations which are neither object defintions
nor function defintions, are declared twice, what's the harm?

The harm is that, for example,
struct fred {int i;};
struct fred {int i;};
will not compile. Note that this is defining a struct, but *not*
defining an object of that struct type.
 
P

pete

Flash said:
Yes, but I'm sure that is not what Ben was referring to.


The harm is that, for example,
struct fred {int i;};
struct fred {int i;};
will not compile. Note that this is defining a struct, but *not*
defining an object of that struct type.

My compiler agrees with you,
but I can't find any words in the standard which call
struct fred {int i;};
a definition.

Got a reference?

I would describe
struct fred {int i;};
as a declaration of a complete struct type.

So far, I only know of 4 kinds of definitions in a translation unit:
1 object
2 function
3 enum
4 typedef

Do I need to add more to the list?
 
B

Ben Pfaff

pete said:
Ben said:
[...on header guards...]
It's also to avoid compilation errors due to redefinitions:
structures, unions, and enumerations (and some other kinds of
entities?) may not be defined more than once.

Object definitions and function definitions
don't belong in header files, do they?

Inline function definitions do make sense in header files.

If declarations which are neither object defintions
nor function defintions, are declared twice, what's the harm?

You can't declare a given typedef more than once, even if the
definitions are identical. Similarly for structures, unions, and
enumerations.
My compiler agrees with you,
but I can't find any words in the standard which call
struct fred {int i;};
a definition.

If your quibble is with me calling a declaration of a structure a
"definition", then please consider me corrected. Now, do you
have a real objection, other than this minor vocabulary issue?
Got a reference?

6.7.2.3 Tags
Constraints
1 A specific type shall have its content defined at most once.

(And wouldn't defining the content of a specific type be a
"definition" of that type?)
 
P

pete

Ben said:
pete said:
Ben said:
[...on header guards...]
It's also to avoid compilation errors due to redefinitions:
structures, unions, and enumerations (and some other kinds of
entities?) may not be defined more than once.

Object definitions and function definitions
don't belong in header files, do they?

Inline function definitions do make sense in header files.
If declarations which are neither object defintions
nor function defintions, are declared twice, what's the harm?

You can't declare a given typedef more than once, even if the
definitions are identical. Similarly for structures, unions, and
enumerations.
My compiler agrees with you,
but I can't find any words in the standard which call
struct fred {int i;};
a definition.

If your quibble is with me calling a declaration of a structure a
"definition", then please consider me corrected. Now, do you
have a real objection, other than this minor vocabulary issue?
Got a reference?

6.7.2.3 Tags
Constraints
1 A specific type shall have its content defined at most once.

(And wouldn't defining the content of a specific type be a
"definition" of that type?)

If it is a "definition" of that type,
then how can I consider you to be corrected?
Terminology is important to me,
even if you're better at it than I am.
If a complete struct declaration is a definition,
then your original statement,

.... is correct and could be shortened to:
"It's also to avoid compilation errors due to redefinitions."
 
G

Gordon Burditt

Object definitions and function definitions
don't belong in header files, do they?

typedefs do.
If declarations which are neither object defintions
nor function defintions, are declared twice, what's the harm?

If you put the same typedef in twice, compilation fails.

Gordon L. Burditt
 
P

pete

Gordon said:
typedefs do.


If you put the same typedef in twice, compilation fails.

Can a "definition" be described as the kind of declaration
which requires a diagnostic if duplicated in the same scope?

Typedefs and enums are classified as definitions in the standard.
 
K

Keith Thompson

pete said:
Can a "definition" be described as the kind of declaration
which requires a diagnostic if duplicated in the same scope?

I don't know. I tried a while ago to construct a reasonable
definition of "definition", but it was contradicted by the standard.
Typedefs and enums are classified as definitions in the standard.

My thought at the time was that a "definition" is anything that
introduces an identifier as a name for some newly created entity.
(For a typedef, the entity in question is a type alias, not the type
itself, since a typedef doesn't create a new type.) Thus an extern
declaration isn't a definition because it merely refers to an entity
defined elsewhere. I don't remember just what shot down my idea.

I'm not convinced the standard uses the term consistently, so now I
just avoid using it without qualification.
 
N

Netocrat

If it is a "definition" of that type,
then how can I consider you to be corrected?
Terminology is important to me,
even if you're better at it than I am.

The poetry of that block of text in isolation deserves a repost.
 
F

Flash Gordon

pete said:
My compiler agrees with you,
but I can't find any words in the standard which call
struct fred {int i;};
a definition.
>
> Got a reference?

In N1124 section 6.7.2.3 Tags it says:
| 6.7.2.3 Tags
| Constraints
| 1 A specific type shall have its content defined at most once.

Everywhere else that I can see it refers to declarations, so I accept
that my terminology was wrong.
I would describe
struct fred {int i;};
as a declaration of a complete struct type.

Having checked the standard I have to agree.
So far, I only know of 4 kinds of definitions in a translation unit:
1 object
2 function
3 enum
4 typedef

Do I need to add more to the list?

No, but this just means there are some times of declaration you can't
repeat within the same scope, which is a bit messy in terms of
terminology IMHO but that is the way it is.
 
P

pete

Keith said:
I don't know. I tried a while ago to construct a reasonable
definition of "definition", but it was contradicted by the standard.


My thought at the time was that a "definition" is anything that
introduces an identifier as a name for some newly created entity.
(For a typedef, the entity in question is a type alias, not the type
itself, since a typedef doesn't create a new type.) Thus an extern
declaration isn't a definition because it merely refers to an entity
defined elsewhere. I don't remember just what shot down my idea.

I recall saying that a typedef dosen't do any more defining
than a complete structure declaration.
Now I'm thinking that maybe a struct declaration does as much
defining as a typedef.
I'm not convinced the standard uses the term consistently, so now I
just avoid using it without qualification.

It would be good, I think, if there was something that all
definitions had in common with each other,
that was unique to definitions.
 
P

pete

Flash said:
pete wrote:

No, but this just means there are some times of declaration you can't
repeat within the same scope, which is a bit messy in terms of
terminology IMHO but that is the way it is.

OK
It's just the above 4 kinds of definitions,
plus complete struct and union declarations.
That's all nonrepeatable declarations that
there can be in a translation unit,
that can't be repeated within the same scope, right?
 
J

Jack Klein


Macros can't be redefined, unless undefine'd first. Macros
effectively have file scope, their only exemption from the scoping
rules that apply to other identifiers is that they can't be hidden by
a redefinition in an inner scope.

Some compilers allow redefinition of macros with identical replacement
text as an extension, but this is non-conforming.
 
T

Tim Rentsch

Jack Klein said:
Macros can't be redefined, unless undefine'd first. Macros
effectively have file scope, their only exemption from the scoping
rules that apply to other identifiers is that they can't be hidden by
a redefinition in an inner scope.

Some compilers allow redefinition of macros with identical replacement
text as an extension, but this is non-conforming.

Really? It seems like it's specifically allowed:

6.10.3

2 An identifier currently defined as an object-like macro shall
not be redefined by another #define preprocessing directive
unless the second definition is an object-like macro definition
and the two replacement lists are identical. Likewise, an
identifier as a function-like macro shall not be redefined by
another #define preprocessing directive unless the second
definition is a function-like macro definition that has the
same number and spelling of parameters, and the two replacement
lists are identical.


6.10.3 p1 gives a definition for replacement lists being identical.
 

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
474,263
Messages
2,571,064
Members
48,769
Latest member
Clifft

Latest Threads

Top