Preprocessor commands usage.

G

G G

#include <stdio.h> // for printf()
int main (void)
{
#define FNORD hello
int FNORD = 23;
printf ("hello, your number today is %d\n", hello);
#define NOBODY_HOME
static unsigned NOBODY_HOME int thing = 42;
printf ("thing, your number today is %d\n", thing);

// This is actually a dangerous way to do this. See
// the section about macro hygiene.

#define SUM(x, y) x + y
int value = SUM(23, 42);
printf ("value, your number today is %d\n", value);
return 0;

} // main

This code comes from, Advanced Mac OS Programming.

I understand the author is trying to demonstrate the preprocessor expansion but
this would not really be done would it.

for example :

#define FNORD hello
int FNORD = 23;
printf ("hello, your number today is %d\n", hello);

is this unusual or should i expect to see a lot of this method, style, in processor
code. (leaning c now) in this example, i'm talking about defining FNORD to hello
then assigning 23 to FNORD. so far, and my experience is limited, i have only
seen #define to replace text, or some type of macro definition. i have seen
an assignment allowed in the program, as done here.

Thanks,

g.
 
G

G G

On Sunday, September 15, 2013 9:04:23 AM UTC-4, Dr Nick wrote:

Thanks Dr. Nick

i have anther question.
another example:
the author is describing in this example the problem of multiple inclusion of
header files. he explains that header files include some header files included in
other header files. (well, he actually says it better than the way i wrote it) so, some
header file are being included more than once... like cdefs.h

The following is the example code:

#include <fcntl.h> // for open()
#include <ulimit.h> // for ulimit()
#include <pthread.h> // for pthread_create()
#include <dirent.h> // for opendir()

int main (void) {
// nobody home
return 0;
} // main

his presented solution is to use the #ifndef directive.

// include-guard.h -- making sure the contents of the header
// are included only once.
#ifndef INCLUDE_GUARD_H
#define INCLUDE_GUARD_H

// Put the real header contents here.

#endif // INCLUDE_GUARD_H

my question is, wouldn't each header file that you did not want to include
twice or more have to appear where the "//Put the real header content here" goes.
in other words doing the following would not eliminate the problem of cdefs.h
being included more than once.
_______________________________________________________________

// include-guard.h -- making sure the contents of the header
// are included only once.
#ifndef INCLUDE_GUARD_H
#define INCLUDE_GUARD_H

// Put the real header contents here.

#include <fcntl.h> // for open()
#include <ulimit.h> // for ulimit()
#include <pthread.h> // for pthread_create()
#include <dirent.h> // for opendir()

#endif // INCLUDE_GUARD_H


int main (void) {
// nobody home
return 0;
} // main
___________________________________________________________________

g.
 
B

Barry Schwarz

On Sunday, September 15, 2013 9:04:23 AM UTC-4, Dr Nick wrote:

Thanks Dr. Nick

i have anther question.
another example:
the author is describing in this example the problem of multiple inclusion of
header files. he explains that header files include some header files included in
other header files. (well, he actually says it better than the way i wrote it) so, some
header file are being included more than once... like cdefs.h

The following is the example code:

#include <fcntl.h> // for open()
#include <ulimit.h> // for ulimit()
#include <pthread.h> // for pthread_create()
#include <dirent.h> // for opendir()

int main (void) {
// nobody home
return 0;
} // main

his presented solution is to use the #ifndef directive.

// include-guard.h -- making sure the contents of the header
// are included only once.
#ifndef INCLUDE_GUARD_H
#define INCLUDE_GUARD_H

// Put the real header contents here.

#endif // INCLUDE_GUARD_H

my question is, wouldn't each header file that you did not want to include
twice or more have to appear where the "//Put the real header content here" goes.
in other words doing the following would not eliminate the problem of cdefs.h
being included more than once.
_______________________________________________________________

// include-guard.h -- making sure the contents of the header
// are included only once.
#ifndef INCLUDE_GUARD_H
#define INCLUDE_GUARD_H

// Put the real header contents here.

#include <fcntl.h> // for open()
#include <ulimit.h> // for ulimit()
#include <pthread.h> // for pthread_create()
#include <dirent.h> // for opendir()

#endif // INCLUDE_GUARD_H


int main (void) {
// nobody home
return 0;
} // main

It is likely that each of the standard headers already has its own
guard. What I hope the author was trying to convey is that your
headers should do the same. If you have
#include "header1.h"
#include "header2.h"
then in header1.h you should have something unique like
#ifndef HEADER1_GUARD
#define HEADER1_GUARD
/*the body of the header
#endif
and in header2 you should have another unique something like
#ifndef HEADER2_GUARD
#define HEADER2_GUARD
/*the body of the header
#endif
 
J

James Kuyper

On Sunday, September 15, 2013 9:04:23 AM UTC-4, Dr Nick wrote:

Thanks Dr. Nick

i have anther question.
another example:
the author is describing in this example the problem of multiple inclusion of
header files. he explains that header files include some header files included in
other header files. (well, he actually says it better than the way i wrote it) so, some
header file are being included more than once... like cdefs.h

The following is the example code:

#include <fcntl.h> // for open()
#include <ulimit.h> // for ulimit()
#include <pthread.h> // for pthread_create()
#include <dirent.h> // for opendir()

int main (void) {
// nobody home
return 0;
} // main

his presented solution is to use the #ifndef directive.

// include-guard.h -- making sure the contents of the header
// are included only once.
#ifndef INCLUDE_GUARD_H
#define INCLUDE_GUARD_H

// Put the real header contents here.

#endif // INCLUDE_GUARD_H

my question is, wouldn't each header file that you did not want to include
twice or more have to appear where the "//Put the real header content here" goes.
in other words doing the following would not eliminate the problem of cdefs.h
being included more than once.
_______________________________________________________________

// include-guard.h -- making sure the contents of the header
// are included only once.
#ifndef INCLUDE_GUARD_H
#define INCLUDE_GUARD_H

// Put the real header contents here.

#include <fcntl.h> // for open()
#include <ulimit.h> // for ulimit()
#include <pthread.h> // for pthread_create()
#include <dirent.h> // for opendir()

#endif // INCLUDE_GUARD_H

You misunderstand the example. Header guards are meant to be put inside
a header file, not in the main code. The words "include-guard.h" at the
start of the example indicated that the example code belongs INSIDE of
the file named "include-garde.h".

Let me give an example from my own code.:

Excerpt from GEO_ephem_attit.c:
...
#include "GEO_earth.h"
#include "GEO_input.h"
#include "GEO_product.h"
...

Every one of those three header files contains the following line:
#include "mapi.h"

Excerpt from mapi.h:
#ifndef MAPI_H
#define MAPI_H
// The main header contents
#endif

When GEO_ephem_attit.c is compiled,

#include "GEO_earth.h"

is replaced by the contents of GEO_earth.h. Going through those lines,
the compiler finds

#include "mapi.h"

and replaces that line with a copy of mapi.h. As a result, MAPI_H gets
#defined, and all of the declarations and #definitions from mapi.h are
processed.
When the compiler gets to

#include "GEO_input.h"

it replaces that line with a copy of GEO_input.h. Going through those
lines, the compiler finds another line that says

#include "mapi.h"

and that line is also replaced by the contents of mapi.h. However, this
time, MAPI_H is already #defined, and as a result the lines between the
#ifndef and the #endif in mapi.h get skipped over. That's good, because
many of those lines would cause identifiers to be declared or #defined
more than once.

The same thing happens when expanding

#include GEO_product.h
 
G

G G

ah.

i think i understand the examples you and Barry have provided.

thanks.

main.m
|
|
-----------------------------------------------------------------------------
| | | |
fcntl.h ulimit.h pthread.h dirent.h
| | | |
| | / | \ | \
_types.h cdefs.h _types.h time.h cdefs.h _types.h cdefs.h

etc.

an example to check understanding:

so, in a headed file (well any file where header files are included) that iwould create i would put #ifndef for cdefs.h if i wanted to include it only once. doing so would defined it once, as the compiler evaluates the other#include(s), of any other header file, cdefs.h would not be included againeven though other C language standard header files may call for cdefsh to be include in them.

#ifndef <cdefs.h>
#define <cdefs.h>
#include <fcntl.h>
#include <ulimit.h>
#include <pthread.h>
#include <dirent.h>
#endif

it is necessary to review a tree of included files and add header files to a #ifndef ... #endif that might be included more than once?

thanks again.
 
J

Joe Pfeiffer

G G said:
ah.

i think i understand the examples you and Barry have provided.

thanks.

main.m
|
|
-----------------------------------------------------------------------------
| | | |
fcntl.h ulimit.h pthread.h dirent.h
| | | |
| | / | \ | \
_types.h cdefs.h _types.h time.h cdefs.h _types.h cdefs.h

etc.

an example to check understanding:

so, in a headed file (well any file where header files are included) that i would create i would put #ifndef for cdefs.h if i wanted to include it only once. doing so would defined it once, as the compiler evaluates the other #include(s), of any other header file, cdefs.h would not be included again even though other C language standard header files may call for cdefsh to be include in them.

#ifndef <cdefs.h>
#define <cdefs.h>
#include <fcntl.h>
#include <ulimit.h>
#include <pthread.h>
#include <dirent.h>
#endif

it is necessary to review a tree of included files and add header files to a #ifndef ... #endif that might be included more than once?

thanks again.

Not quite -- when you create a header file, you take the steps to
protect your own file from being multiply included. All the header
files under /usr/include/ are supposed to be so protected (but if
somebody shows me an example of one that isn't, I certainly won't be
surprised). If I look at /usr/include/fcntl.h I find (right after the
copyright notice)

#ifndef _FCNTL_H
#define _FCNTL_H 1

and I find at the end of the file

#endif /* fcntl.h */

So you can safely do something in your code that ends up looking like

#include <fcntl.h>
#include <fcntl.h>

and the first time it's included everything in it will be defined
appropriately, but the second time nothing will happen.

You don't need to worry about the possibility of #including <fcntl.h>
twice, as the file itself protects you from bad things happening if you
do.

Note that your

#ifndef <cdefs.h>

won't compile, since you have to have an identifier there, not something
with <> around it.
 
J

James Kuyper

ah.

i think i understand the examples you and Barry have provided.

I disagree.
an example to check understanding:

so, in a headed file (well any file where header files are included)
that i would create i would put #ifndef for cdefs.h if i wanted to
include it only once. doing so would defined it once, as the compiler
evaluates the other #include(s), of any other header file, cdefs.h
would not be included again even though other C language standard
header files may call for cdefsh to be include in them.

No. You only put include guards in header files, you never place them in
your *.c files. The header guard goes inside the header file that it
gaurds. The header guard DOES not prevent the header file from being
#included multiple times. What it does is make sure, if the header file
does get #included multiple times, that the main part of the header file
only gets processed the first time.

cdefs.h is not a C standard header - the only C standard header that you
mentioned was time.h. Most of the others are POSIX headers, but cdefs.h
seems to be linux-specific. There's no _types.h file on my system, so I
have no idea what that is.
#ifndef <cdefs.h>
#define <cdefs.h>
#include <fcntl.h>
#include <ulimit.h>
#include <pthread.h>
#include <dirent.h>
#endif

In addition to putting your header guard in the wrong location, you've
also got the wrong syntax. There's an example of the correct syntax
inside of cdefs.h on my system, there's the following lines:

#ifndef _SYS_CDEFS_H
#define _SYS_CDEFS_H
....
#endif

Note that it's up to the designer of the header file to decide what name
to use for the include guard; it doesn't have to have any connection to
the actual header file name.

Note also that identifiers starting with an underscore followed by a
capital letter are reserved - that means you can't use them. The reason
you can't use them is so that the implementors of the C standard library
CAN use them. The use of such names in cdefs.h suggests either that it
is provided as an extension by the same people who provided the C
standard library, or that a serious mistake was made. YOU should never
use such names in your own
it is necessary to review a tree of included files and add header
files to a #ifndef ... #endif that might be included more than once?

No, it's not necessary to do any such analysis. You should put a header
guard in every header file you write. When I write header files, the
first thing I put in them is the header guard, including the following
#endif. I fill in the body of the header later.
 
B

Barry Schwarz

ah.

i think i understand the examples you and Barry have provided.

thanks.

main.m
|
|
-----------------------------------------------------------------------------
| | | |
fcntl.h ulimit.h pthread.h dirent.h
| | | |
| | / | \ | \
_types.h cdefs.h _types.h time.h cdefs.h _types.h cdefs.h

etc.

an example to check understanding:

so, in a headed file (well any file where header files are included) that i would create i would put #ifndef for cdefs.h if i wanted to include it only once. doing so would defined it once, as the compiler evaluates the other #include(s), of any other header file, cdefs.h would not be included again even though other C language standard header files may call for cdefsh to be include in them.

NO.
1 - You only put a guard INSIDE a header file you create.
2 - You do not worry about system headers.
3 - You do not depend on someone using your header (that means you
too) taking precautions in the source file containing the #include
directive. By virtue of step 1, the header file protects itself,
unless a perverse user issues the #undef directive (in which case he
deserves what he gets).
4 - Just out of curiosity, since several header files need
_types.h, how do you think any code in your source file could insure
_types.h is included exactly once when including more than one
"parent" header?
#ifndef <cdefs.h>
#define <cdefs.h>
#include <fcntl.h>
#include <ulimit.h>
#include <pthread.h>
#include <dirent.h>
#endif

it is necessary to review a tree of included files and add header files to a #ifndef ... #endif that might be included more than once?

It is not necessary (and not recommended) to review system headers.
They frequently contain system dependent constructs which you would be
wise not to emulate. The C and posix standards tell you everything
you need to know to use them correctly for most tasks.

It is definitely unnecessary to construct include trees for system
headers. Whether you need to do so for your headers is a decision
only you can make.
 
K

Kenny McCormack

James Kuyper said:
There's no _types.h file on my system, so I have no idea what that is.

You do know about this newfangled thing called "Google", don't you?

It's really cool. It allows you to learn about all sorts of stuff that you
don't have direct physical access to. You really should check it out.

--
- Since the shootings on Friday, the ultra-defensive [maybe wrongly
- hyphenated, but that would be fitting] Roy "News" LIEberman has posted
- at least 90 times, and almost every single post is about his obsessive
- knee-jerk loonball [wacko] gun politics. How much longer before the
- authorities [police] finally disable the trip wires and confiscate the
- arsenal in his St. Louie hovel?

So true. So true.
 
K

Keith Thompson

G G said:
i think i understand the examples you and Barry have provided.

thanks.

main.m
|
|
-----------------------------------------------------------------------------
| | | |
fcntl.h ulimit.h pthread.h dirent.h
| | | |
| | / | \ | \
_types.h cdefs.h _types.h time.h cdefs.h _types.h cdefs.h

etc.

an example to check understanding:

so, in a headed file (well any file where header files are included)
that i would create i would put #ifndef for cdefs.h if i wanted to
include it only once. doing so would defined it once, as the compiler
evaluates the other #include(s), of any other header file, cdefs.h
would not be included again even though other C language standard
header files may call for cdefsh to be include in them.

#ifndef <cdefs.h>
#define <cdefs.h>
#include <fcntl.h>
#include <ulimit.h>
#include <pthread.h>
#include <dirent.h>
#endif

it is necessary to review a tree of included files and add header
files to a #ifndef ... #endif that might be included more than once?

(Please wrap your lines at 80 columns or less, preferably about 72.)

No, I don't think you get it.

First off, "#ifndef <cdefs.h>" is a syntax error; the argument of
#ifndef must be a valid identifier, which <cdefs.h> is not.

Each header has its own header guard; no other file has to be aware of
it.

For example, if you have a header file called "cdefs.h", then its first
two lines should be something like:

#ifndef H_CDEFS
#define H_CDEFS

and its last line should be

#endif

Any other file that needs to use the declarations in cdefs.h will
simply use:

#include "cdefs.h"

(Note the use of "..." rather than <...>; the latter is for system
headers.)

That's about all there is to it. It's up to the author of each
header file to pick a macro name that's unique to that file.

The reason for header guards is to avoid having the same declaration
appear more than once. A source file that includes "cdefs.h"
might also include another header file that includes "cdefs.h".
The #ifndef sequence guarantees that, no matter how many times
"cdefs.h" is included directly or indirectly, its declarations will
appear only once.

Incidentally, your picture refers to a file called "main.m".
The ".m" suffix is commonly used for Objective-C source files.
If you're programming on Objective-C, you're in the wrong place;
it's very similar to C in many ways, but there might be differences
in the way headers are handled.
 
G

G G

ah, ok, i was way off in my thinking . i'm glad you guys explained header guards.

thanks everyone.

g.
 
E

Edward A. Falk

I understand the author is trying to demonstrate the preprocessor expansion but
this would not really be done would it.

No, it wouldn't. Those were really awful examples.
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top