Problems about conditional compilation

W

wanghz

Hi,

Could I ask some questions about the conditional compilaion? Suppose I
have three simple files: a.c, b.c and c.h

/* --------a.c--------- */
#include <stdio.h>
#include "c.h"

int main()
{
int temp = XXXX;
printf("%d\n", temp);
f();
return 0;
}


/* --------b.c--------- */
#include <stdio.h>
#include "c.h"

int f()
{
int temp = XXXX;
printf("%d\n", temp);
return 0;
}


/* -------c.h--------- */
#ifndef C_H_
#define C_H_
#define XXXX 100
#else
#define XXXX 900
#endif

Then, when I compile them together by gcc a.c b.c, the result shows:
100
100

I wonder why the conditional compilation does not work. I mean, when
c.h is included by a.c and b.c respectively, XXXX should by defined as
two different values. What's wrong with this understanding?

In fact, this problem comes from another one. When I try to define a
function in the header file c.h (I know, this is not a good style),
compiler complains there are duplicated definition for that function.
But the function definition section is wrapped by compilation
directives, so it should not be included twice at all.

I feel very confused about conditional compilation. Please help me or
give some clues to make it clear. Thank you all in advance.
 
E

Emmanuel Delahaye

wanghz wrote on 11/09/05 :
Hi,

Could I ask some questions about the conditional compilaion? Suppose I
have three simple files: a.c, b.c and c.h

/* --------a.c--------- */
#include <stdio.h>
#include "c.h"

int main()
{
int temp = XXXX;
printf("%d\n", temp);
f();
return 0;
}

/* --------b.c--------- */
#include <stdio.h>
#include "c.h"

int f()
{
int temp = XXXX;
printf("%d\n", temp);
return 0;
}

/* -------c.h--------- */
#ifndef C_H_
#define C_H_
#define XXXX 100
#else
#define XXXX 900
#endif

Then, when I compile them together by gcc a.c b.c, the result shows:
100
100
Fine.

I wonder why the conditional compilation does not work.

It does.
I mean, when
c.h is included by a.c and b.c respectively,

'respectively''is the important word.
XXXX should by defined as
two different values. What's wrong with this understanding?

It's all wrong. The guard trick is against multiple inclusions, not
against multple definitions.
In fact, this problem comes from another one. When I try to define a
function in the header file c.h

Don't do that.
(I know, this is not a good style),

for a good reason your are to discover.
compiler complains there are duplicated definition for that function.
Sure.

But the function definition section is wrapped by compilation
directives, so it should not be included twice at all.

Why ?

The guard protects against this :

/* b.h */
<...>
#include "a.h"
<...>


/* xxx.c */
#include "a.h"
#include "b.h" /* second inclusion */
I feel very confused about conditional compilation. Please help me or
give some clues to make it clear. Thank you all in advance.

It's quite simple. There are usage rules that are to be followed:

- a header contains not more that the following :

* #include directives
* public macros definitions
* public constants definitions
* public types definitions
* public structures definitions
* public unions definitions
* public inline functions definitions [C99]
* public functions declarations (prototyped form highly recommended)
* public object declarations (extern)

- A header is guarded (again multiple inclusions)

#ifndef H_XXX
#define H_XXX

/* include the above here. */

#endif /* guard */

You can burn the rules, but don't come here an cry.


--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

I once asked an expert COBOL programmer, how to
declare local variables in COBOL, the reply was:
"what is a local variable?"
 
E

Emmanuel Delahaye

(supersedes <[email protected]>)

wanghz wrote on 11/09/05 :
Hi,

Could I ask some questions about the conditional compilaion? Suppose I
have three simple files: a.c, b.c and c.h

/* --------a.c--------- */
#include <stdio.h>
#include "c.h"

int main()
{
int temp = XXXX;
printf("%d\n", temp);
f();
return 0;
}

/* --------b.c--------- */
#include <stdio.h>
#include "c.h"

int f()
{
int temp = XXXX;
printf("%d\n", temp);
return 0;
}

/* -------c.h--------- */
#ifndef C_H_
#define C_H_
#define XXXX 100
#else
#define XXXX 900
#endif

Then, when I compile them together by gcc a.c b.c, the result shows:
100
100
Fine.

I wonder why the conditional compilation does not work.

It does.
I mean, when
c.h is included by a.c and b.c respectively,

'respectively''is the important word.
XXXX should by defined as
two different values. What's wrong with this understanding?

It's all wrong. The guard trick is against multiple *inclusions*, not
against multiple *definitions*.
In fact, this problem comes from another one. When I try to define a
function in the header file c.h

Don't do that.
(I know, this is not a good style),

for good reasons your are to discover.
compiler complains there are duplicated definition for that function.
Sure.

But the function definition section is wrapped by compilation
directives, so it should not be included twice at all.

Why ?

The guard protects against this :

/* b.h */
<...>
#include "a.h"
<...>

/* xxx.c */
#include "a.h"
#include "b.h" /* second inclusion */
I feel very confused about conditional compilation. Please help me or
give some clues to make it clear. Thank you all in advance.

It's quite simple. There are usage rules that are to be followed:

- A header contains not more that the following (in that order):

* #include directives
* public macros definitions
* public constants definitions
* public types definitions
* public structures definitions
* public unions definitions
* public inline functions definitions [C99]
* public functions declarations (prototyped form highly recommended)
* public object declarations (extern)

- A header is guarded (against multiple inclusions)

#ifndef H_XXX
#define H_XXX

/* include the above here. */

#endif /* guard */

You can burn out the rules, but don't come here an cry.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

I once asked an expert COBOL programmer, how to
declare local variables in COBOL, the reply was:
"what is a local variable?"
 
M

Marc Thrun

wanghz said:
Hi,

Could I ask some questions about the conditional compilaion? Suppose I
have three simple files: a.c, b.c and c.h

/* --------a.c--------- */
#include <stdio.h>
#include "c.h"

int main()
{
int temp = XXXX;
printf("%d\n", temp);
f();
return 0;
}


/* --------b.c--------- */
#include <stdio.h>
#include "c.h"

int f()
{
int temp = XXXX;
printf("%d\n", temp);
return 0;
}


/* -------c.h--------- */
#ifndef C_H_
#define C_H_
#define XXXX 100
#else
#define XXXX 900
#endif

Then, when I compile them together by gcc a.c b.c, the result shows:
100
100

I wonder why the conditional compilation does not work. I mean, when
c.h is included by a.c and b.c respectively, XXXX should by defined as
two different values. What's wrong with this understanding?

In fact, this problem comes from another one. When I try to define a
function in the header file c.h (I know, this is not a good style),
compiler complains there are duplicated definition for that function.
But the function definition section is wrapped by compilation
directives, so it should not be included twice at all.

I feel very confused about conditional compilation. Please help me or
give some clues to make it clear. Thank you all in advance.

gcc compiles every .c file as a single "program" (dont know a proper
name, correct me please if you know one), so an include in a.c does not
interfere with an include in b.c and vice versa. The "programs" will
then be linked together to the complete executable.

So C_H_ is never defined before you include c.h and hence it always
defines XXXX to be 100. The same applies to your function problem.

HTH
 
M

Michael Mair

wanghz said:
Hi,

Could I ask some questions about the conditional compilaion? Suppose I
have three simple files: a.c, b.c and c.h

/* --------a.c--------- */
#include <stdio.h>
#include "c.h"

int main()
{
int temp = XXXX;
printf("%d\n", temp);
f();
return 0;
}


/* --------b.c--------- */
#include <stdio.h>
#include "c.h"

int f()
{
int temp = XXXX;
printf("%d\n", temp);
return 0;
}


/* -------c.h--------- */
#ifndef C_H_
#define C_H_
#define XXXX 100
#else
#define XXXX 900
#endif

Then, when I compile them together by gcc a.c b.c, the result shows:
100
100

I wonder why the conditional compilation does not work. I mean, when
c.h is included by a.c and b.c respectively, XXXX should by defined as
two different values. What's wrong with this understanding?

a.c and b.c are two separate translation units. They do not "see"
each other at compile time.
Most of the things the preprocessor does can be seen as some sort
of text replacement.

So, in a.c _and_ b.c, c.h is included for the first time, respectively,
thus C_H_ is not defined and you arrive at the first #define directive.

Only if you have
#include "c.h"
....
#include "c.h"
where one or both include directives can come in directly or indirectly
(i.e. via another included header), you run into the second #define.
However, this effectively means
#define XXXX 100
#define XXXX 900
which probably is not what you want at all.

Usually, the inclusion guards are there to avoid _double_ definitions
and ill effects stemming from them.

In fact, this problem comes from another one. When I try to define a
function in the header file c.h (I know, this is not a good style),
compiler complains there are duplicated definition for that function.
But the function definition section is wrapped by compilation
directives, so it should not be included twice at all.

I feel very confused about conditional compilation. Please help me or
give some clues to make it clear. Thank you all in advance.

The canonical and correct way of handling this:

/* --------a.c--------- */
#include <stdio.h>
#include "b.h"
#include "c.h"

int main (void)
{
printf("%d\n", xxxx);
g();
f();
return 0;
}

/* --------b.h--------- */
#ifndef B_H_
#define B_H_

void f (void);

#endif
/* --------b.c--------- */
#include <stdio.h>
#include "b.h"
#include "c.h"

void f (void)
{
printf("%d\n", xxxx);
g();
}

/* -------c.h--------- */
#ifndef C_H_
#define C_H_

extern int xxxx;

void g (void);

#endif

/* -------c.c--------- */
#include "c.h"

int xxxx = 42;

void g (void)
{
xxxx++;
}


Note that declaring xxxx in this way is a bad idea at best.
Giving xxxx internal linkage and creating a function returning
the value of xxxx would be safer.


Cheers
Michael
 
I

Irrwahn Grausewitz

wanghz said:
Hi,

Could I ask some questions about the conditional compilaion? Suppose I
have three simple files: a.c, b.c and c.h

/* --------a.c--------- */
#include <stdio.h>
#include "c.h"

int main()
{
int temp = XXXX;
printf("%d\n", temp);
f();
return 0;
}


/* --------b.c--------- */
#include <stdio.h>
#include "c.h"

int f()
{
int temp = XXXX;
printf("%d\n", temp);
return 0;
}


/* -------c.h--------- */
#ifndef C_H_
#define C_H_
#define XXXX 100
#else
#define XXXX 900
#endif

Then, when I compile them together by gcc a.c b.c, the result shows:
100
100

Of course, since c.h is included once by a.c and, *independently*,
by b.c. Your multiple inclusion guards will work only, if c.h is
included more than once by one of your .c files. The macro
definitions in a.c are invisible in b.c.
I wonder why the conditional compilation does not work. I mean, when
c.h is included by a.c and b.c respectively, XXXX should by defined as
two different values. What's wrong with this understanding?

See above.
In fact, this problem comes from another one. When I try to define a
function in the header file c.h (I know, this is not a good style),

Indeed.
compiler complains there are duplicated definition for that function.

Actually, it's the linker which complains, since you generated
duplicate code for the functions, for the reasons given above.
But the function definition section is wrapped by compilation
directives, so it should not be included twice at all.

But it's included once by each of your source files, so you end up
having duplicate code in linking stage.
I feel very confused about conditional compilation. Please help me or
give some clues to make it clear. Thank you all in advance.

Try this, for example:

/* --------a.c--------- */
#include <stdio.h>

#include "c.h"

int main( void )
{
int temp = XXXX;
printf("%d\n", temp);
f();
return 0;
}


/* --------b.c--------- */
#include <stdio.h>

#define USE_ALTERNATE_XXXX

#include "c.h"

int f()
{
int temp = XXXX;
printf("%d\n", temp);
return 0;
}


/* -------c.h--------- */
#ifndef USE_ALTERNATE_XXXX
#define XXXX 100
#else
#define XXXX 900
#endif


Best regards
 
W

wanghz

Hi,

Thank you for your reply :)

I think I might have understood what is the fallacy by learning your
suggestion. Do you mean that the muliple inclusions guard is used in a
compliation unit only? That is, when precompiler is processing a
source file, for example, a.c, the guard prevent including the same
header more than one times in this file only? When it turns to a new
source file, the precomilation will restart and all remembered
defined's would be discarded. So the guard does not try to prevent
including the same header file at different source files?

I don't know whether my understanding is correct this time.
 
E

Emmanuel Delahaye

wanghz wrote on 11/09/05 :
I think I might have understood what is the fallacy by learning your
suggestion. Do you mean that the muliple inclusions guard is used in a
compliation unit only?
Yes.

That is, when precompiler is processing a

I don't know what a 'precompiler' is. Maybe you meant the
'preprocessor'.
source file, for example, a.c, the guard prevent including the same
header more than one times in this file only?
Yes.

When it turns to a new
source file, the precomilation will restart and all remembered
defined's would be discarded. So the guard does not try to prevent
including the same header file at different source files?

I don't know whether my understanding is correct this time.

Sounds all good to me.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"There are 10 types of people in the world today;
those that understand binary, and those that dont."
 
W

wanghz

Thank you all in advance.

All of your replies have give me a good tutorial on this topic, and
make me clear on many other related problems too.

Thank you all again!
 
K

Kenneth Brody

wanghz said:
Hi,

Could I ask some questions about the conditional compilaion? Suppose I
have three simple files: a.c, b.c and c.h
[... a.c and b.c print the value of XXXX ...]
/* -------c.h--------- */
#ifndef C_H_
#define C_H_
#define XXXX 100
#else
#define XXXX 900
#endif

Then, when I compile them together by gcc a.c b.c, the result shows:
100
100

I wonder why the conditional compilation does not work. I mean, when
c.h is included by a.c and b.c respectively, XXXX should by defined as
two different values. What's wrong with this understanding?

You misunderstanding is believing that a.c and b.c are being compiled
as a single unit when they are not. Each source file listed on the
command line is compiled separately. Anything done while compiling
the first file (a.c) is thrown out when the second file (b.c) is
compiled.

Therefore, a.c's define of C_H_ no longer exists when the compiler
starts to compile b.c

Also, consider this... If you expected C_H_ to retain its definition,
why did you not expect XXXX to retain its, and therefore give a
redefinition error?

[...]

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:[email protected]>
 
D

Das

wanghz said:
Hi,

Thank you for your reply :)

I think I might have understood what is the fallacy by learning your
suggestion. Do you mean that the muliple inclusions guard is used in a
compliation unit only? That is, when precompiler is processing a
source file, for example, a.c, the guard prevent including the same
header more than one times in this file only?

Yes. That is the use of guards.
When it turns to a new
source file, the precomilation will restart and all remembered
defined's would be discarded. So the guard does not try to prevent
including the same header file at different source files?

A new file is a new job to be processed, So the state is changed to
originals.
I don't know whether my understanding is correct this time.

Thanks
Ashok.
 
S

samrox

Das said:
Yes. That is the use of guards.


A new file is a new job to be processed, So the state is changed to
originals.


Thanks
Ashok.

the question is ridiculous. please go back to school!
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top