Detecting typedef at preprocessing time

T

Thomas Carter

Imagine that there is some include file f.h that contains the following
line:

typedef unsigned int ui32 ;

My question is: If I have a C source file F.c that includes f.h, is it
possible for the preprocessor to detect that ui32 already exists, when
preprocessing F.c? The idea is that F.c will typedef ui32 as above if and
only if such typedef is not already in some include file used by F.c.
 
I

Ivanna Pee

Thomas said:
Imagine that there is some include file f.h that contains the following
line:

typedef unsigned int ui32 ;

My question is: If I have a C source file F.c that includes f.h, is it
possible for the preprocessor to detect that ui32 already exists, when
preprocessing F.c? The idea is that F.c will typedef ui32 as above if and
only if such typedef is not already in some include file used by F.c.

/* File f.h */

#ifndef _UI32
#define _UI32
typedef unsigned int ui32 ;
#endif
 
W

Walter Roberson

Imagine that there is some include file f.h that contains the following
line:
typedef unsigned int ui32 ;
My question is: If I have a C source file F.c that includes f.h, is it
possible for the preprocessor to detect that ui32 already exists, when
preprocessing F.c? The idea is that F.c will typedef ui32 as above if and
only if such typedef is not already in some include file used by F.c.


No, not without assistance such as defining a macro to indicate the
existance of the feature.

The only currencies of the preprocessor are macros and arithmetic
constant expressions.
 
M

Michael Mair

Thomas said:
Imagine that there is some include file f.h that contains the following
line:

typedef unsigned int ui32 ;

My question is: If I have a C source file F.c that includes f.h, is it
possible for the preprocessor to detect that ui32 already exists, when
preprocessing F.c? The idea is that F.c will typedef ui32 as above if and
only if such typedef is not already in some include file used by F.c.

The preprocessor itself cannot interpret typedefs.

Usually, you want to have only one such typedef.
As you can protect the contents of a header against multiple
inclusion, the usual construct is

,-- mytypes.h --
#ifndef MY_TYPES_H__
#define MY_TYPES_H__
.....
typedef unsigned int ui32;
.....
#endif
`----

If you need ui32 or another of the typed from "mytypes.h", then
#include "mytypes.h"
If any header needs to provide ui32, too, then make sure it
includes mytypes.h as well.

If you are in the rare and unfortunate situation that you can
either have an implementation typedef or have to provide one of
your own, then do the same: There usually is a, possibly
implementation specific, means to detect whether the type already
is there. Use this in your header mytypes.h. Whenever this header
is included, you can be sure that you have either one typedef or
the other -- but that it is there.
Usually better: Provide your own typedef name.

Example: You need a signed integer type with at least 24 bits and
decide you want to try first whether <stdint.h> defines one before
typedef'ing your own:

One solution:
,-- mytypes.h --
#ifndef MY_TYPES_H__
#define MY_TYPES_H__
#include <limits.h>
#include <stdint.h>
.....
# ifndef INT_LEAST24_MAX
typedef signed long int_least24_t;
/* In order to "normalise" the picture: provide limits */
# define INT_LEAST24_MAX LONG_MAX
# define INT_LEAST24_MIN LONG_MIN
# endif
.....
#endif
`----

Another solution (one I would favour):
,-- mytypes.h --
#ifndef MY_TYPES_H__
#define MY_TYPES_H__
#include <limits.h>
#include <stdint.h>
.....
# ifdef INT_LEAST24_MAX
typedef int_least24_t sint24;
/* Optional: Provide limits */
# else
typedef signed long sint24;
/* Optional: Provide limits */
# endif
.....
#endif
`----


Cheers
Michael
 
M

Michael Mair

Ivanna said:
/* File f.h */

#ifndef _UI32
#define _UI32

In principle correct but the (macro) identifiers starting with
_ should be left to the implementation -- this is not the exact
truth but you are on the safe side if you keep to it.
typedef unsigned int ui32 ;
#endif


Cheers
Michael
 
J

John Bode

Thomas said:
Imagine that there is some include file f.h that contains the following
line:

typedef unsigned int ui32 ;

My question is: If I have a C source file F.c that includes f.h, is it
possible for the preprocessor to detect that ui32 already exists, when
preprocessing F.c? The idea is that F.c will typedef ui32 as above if and
only if such typedef is not already in some include file used by F.c.

In f.h:

#define UI32_TYPEDEF
typedef ... ui32;

in F.c:

#ifndef UI32_TYPEDEF
typedef ... ui32;
#endif
 
T

Thomas Carter

Imagine that there is some include file f.h that contains the following
line:

typedef unsigned int ui32 ;

My question is: If I have a C source file F.c that includes f.h, is it
possible for the preprocessor to detect that ui32 already exists, when
preprocessing F.c? The idea is that F.c will typedef ui32 as above if and
only if such typedef is not already in some include file used by F.c.

Thanks everybody for your suggestions. I forgot to point out that, in
general, one is not allowed to modify f.h. I guess that with such
restriction, what I want to do in general just can't be done.
 
W

Walter Roberson

Thanks everybody for your suggestions. I forgot to point out that, in
general, one is not allowed to modify f.h. I guess that with such
restriction, what I want to do in general just can't be done.

You might want to look at "autoconf" as a mechanism to figure out
whether the typedef is present and to generate an include file with
the appropriate macro definition. "autoconf" (and other such tools)
are outside of the rhelm of standard C, but it is plausibly ported
to all of the environments you will care about.
 
K

Keith Thompson

Thomas Carter said:
Thanks everybody for your suggestions. I forgot to point out that, in
general, one is not allowed to modify f.h. I guess that with such
restriction, what I want to do in general just can't be done.

There are ways to do it if you're wiling to go beyond the scope of
what the compiler alone can do for you.

For example, you can create a small test program that attempts to use
ui32:

#include "f.h"
#include <stdio.h>
int main(void)
{
ui32 dummy;
printf("ok\n");
return 0;
}

Attempt to compile and execute the program. If it prints "ok", the
typedef exists; otherwise, it doesn't. Use this result to generate,
say, another header file to be included by F.c (is that really an
uppercase "F"?). The generated header file might just include a
series of #define directives. Depending on your environment, a
reasonably simple shell script, batch file, or equivalent should do
the job.

Your F.c might then contain something like this:

#include "f.h"
#include "config.h"
....
#ifndef UI32_DEFINED
typedef unsigned int ui32;
#endif
....

If you're doing this kind of thing a lot, you might consider using a
tool like GNU autoconf (which is off-topic here, but easy to google).

You also need to be aware of what assumptions you're making. Type
unsigned int isn't necessarily 32 bits; it can be 16, 64, or even 47,
and even if it's 32 bits, some of them could be padding bits. There
might not even be a 32-bit integer type (though there will always be
some integer type that's *at least* 32 bits).

Ideally, you should use the <stdint.h> header, which defines typedefs
such as uint32_t, along with macros that let you determine whether
they're defined. The <stdint.h> header is new in C99, but it's not
difficult to implement most of it in C90; see Doug Gwyn's q8,
<http://www.lysator.liu.se/c/q8/index.html>.
 
J

Joe Estock

Michael said:
In principle correct but the (macro) identifiers starting with
_ should be left to the implementation -- this is not the exact
truth but you are on the safe side if you keep to it.



Cheers
Michael

I agree with Michael. I normally follow the convention:

#ifndef H_FILENAME_H
....
#endif /* !defined(H_FILENAME_H) */

In reality it doesn't really matter what naming convention you use so
long as you are consistent throughout the code.

Hope that helps,

Joe
 
M

Me

Thomas said:
Imagine that there is some include file f.h that contains the following
line:

typedef unsigned int ui32 ;

My question is: If I have a C source file F.c that includes f.h, is it
possible for the preprocessor to detect that ui32 already exists, when
preprocessing F.c? The idea is that F.c will typedef ui32 as above if and
only if such typedef is not already in some include file used by F.c.

You're better off using C++ for this which ignores duplicate typedefs.
If you decide to still do this with C, be very careful how you do this
because the majority of C compilers don't do any type safe linking so
you can run into strange and extremely hard to figure out problems if
code crosses 2 translation units and these typedefs get out of sync
somehow:

/* a.c */
typedef unsigned int ui32;
....

/* b.c */
typedef unsigned long ui32;
....

if the compiler is strict about aliasing (even if the representation of
unsigned int and unsigned long just happen to be the same on your
platform).
 
K

Keith Thompson

Me said:
You're better off using C++ for this which ignores duplicate typedefs.
If you decide to still do this with C, be very careful how you do this
because the majority of C compilers don't do any type safe linking so
you can run into strange and extremely hard to figure out problems if
code crosses 2 translation units and these typedefs get out of sync
somehow:

/* a.c */
typedef unsigned int ui32;
...

/* b.c */
typedef unsigned long ui32;
...

if the compiler is strict about aliasing (even if the representation of
unsigned int and unsigned long just happen to be the same on your
platform).

That's what header files are for.

You have a single definition for ui32, and every file that needs it
has a #include for the appropriate header (which has guards to avoid
multiple definitions).
 
P

pete

Joe said:
I agree with Michael. I normally follow the convention:

#ifndef H_FILENAME_H
...
#endif /* !defined(H_FILENAME_H) */

In reality it doesn't really matter what naming convention you use so
long as you are consistent throughout the code.


Also, you should make sure that the naming convention,
is one that you reserve strictly for header file guards.
I used to use H_FILENAME for header guards,
but then I had a program with files sort.c and sort.h,
with a H_SORT header guard macro.
and anther file h_sort.c which also defined a macro H_SORT,
so I added the trailing underscore to the header guards
and I use that H_FILENAME_ convention only for header guards only.

I'd say that H_FILENAME_H is at least as good or better,
as long as you keep it straight that your program
won't generate an H_/**/_H macro for any other purpose.
 

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
474,176
Messages
2,570,950
Members
47,503
Latest member
supremedee

Latest Threads

Top