#if typedef()

K

Kenneth Brody

Is there any way to know if there is a typedef of a given name?

Specifically, I need to know if the compiler has a 64-bit integer type,
and need to know if "int64_t" exists. Something like this pseudo-code:

#if typedef(int64_t)
typedef int64_t MY_BIG_INT
#elif typedef(long long)
typedef long long MY_BIG_INT
#else
typedef long MY_BIG_INT
#endif

(Yes, this program needs to work on systems which don't have a 64-bit
integers, and it needs to take advantage of them if they are there.)

Also, what is the standard include file which would be needed to have
the int64_t typedef included? I see it in <stdint.h> on one compiler
I have, and <native.h> on another. I don't see these headers being
included by other standard headers on these systems.

--
+-------------------------+--------------------+-----------------------------+
| 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]>
 
W

Walter Roberson

Is there any way to know if there is a typedef of a given name?
Specifically, I need to know if the compiler has a 64-bit integer type,
and need to know if "int64_t" exists.


There is no portable way to test that in C89 (I'm not familiar enough
with C99 to know if it were extended in that regard, but I suspect not.)


The usual way to handle this is to have a meta level that tests
for the existance of appropriate types or functions and sets
preprocessing tokens appropriately in a constructed include file
that the rest of the code imports.
 
K

Kenneth Brody

Walter said:
There is no portable way to test that in C89 (I'm not familiar enough
with C99 to know if it were extended in that regard, but I suspect not.)

I can't depend on C99 being available, so that's not really relevent.
The usual way to handle this is to have a meta level that tests
for the existance of appropriate types or functions and sets
preprocessing tokens appropriately in a constructed include file
that the rest of the code imports.

Well, we already have a bunch of config.h files for different platforms
to define such things native byte order (yes, some parts of the code need
to know that), whether "void" is available (we used to run on platforms
that had no "void" type), which type of varargs are needed, and so on. I
was just hoping to avoid yet another entry.

I guess I'll probably end up going with "assume there's an int64_t type
unless the config file defines NO_INT64_T", or something like that.

--
+-------------------------+--------------------+-----------------------------+
| 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]>
 
K

Keith Thompson

Kenneth Brody said:
Is there any way to know if there is a typedef of a given name?
No.

[snip]

Also, what is the standard include file which would be needed to have
the int64_t typedef included? I see it in <stdint.h> on one compiler
I have, and <native.h> on another. I don't see these headers being
included by other standard headers on these systems.

In C99, int64_t is defined in <stdint.h>, but the C99 standard is not
universally supported. Strictly speaking, int64_t is optional; it
will be defined only if the implementation has a two's complement
integer type with a width of exactly 64 bits and no padding. In
practice, since C99 requires long long to be at least 64 bits, I'd be
surprised to see a C99 implementation that doesn't have int64_t.

Given a C99 implementation, the macro INT64_MAX will be defined in
<stdint.h> if and only if int64_t is defined, so you can use
#ifdef INT64_MAX

You can check whether you have a C99 implementation with

#if __STDC_VERSION__ >= 199901L

A pre-C99 compiler is allowed, but not required, to define int64_t in
an implementation-specific header -- or it can call it int_64_t, or
anything it likes. There's no way in the preprocessor to test whether
a given header exists. You pretty much have to track down the details
for all the implementations you need to support, and write custom code
for each.

Perhaps the best approach is to use your own <stdint.h> (or, more
properly, "stdint.h") header to be used with pre-C99 compilers. See
<http://www.lysator.liu.se/c/q8/> for a public domain implementation.

Note that __STDC_VERSION__ >= 199901L doesn't necessarily imply that
the <stdint.h> header *doesn't* exist. Some compilers might provide
partial C99 support.
 
K

Keith Thompson

Kenneth Brody said:
Well, we already have a bunch of config.h files for different platforms
to define such things native byte order (yes, some parts of the code need
to know that), whether "void" is available (we used to run on platforms
that had no "void" type), which type of varargs are needed, and so on. I
was just hoping to avoid yet another entry.

Looks like you'll need yet another entry.
I guess I'll probably end up going with "assume there's an int64_t type
unless the config file defines NO_INT64_T", or something like that.

You may find that giving a flag a negative name will cause confusion.
I find thinks like
#ifdef NO_INT64_T
or
#if !defined(NO_INT_64_T)
more difficult to read than
#ifdef HAS_INT64_T
or
#if defined(HAS_INT_64_T)
 
F

Flash Gordon

Kenneth said:
Is there any way to know if there is a typedef of a given name?
No.

Specifically, I need to know if the compiler has a 64-bit integer type,
and need to know if "int64_t" exists. Something like this pseudo-code:

#if typedef(int64_t)
typedef int64_t MY_BIG_INT
#elif typedef(long long)

"long long", on systems which have it, won't *be* a type def.
typedef long long MY_BIG_INT
#else
typedef long MY_BIG_INT
#endif

(Yes, this program needs to work on systems which don't have a 64-bit
integers, and it needs to take advantage of them if they are there.)

For that you obviously need rather more work than merely using the right
type.
Also, what is the standard include file which would be needed to have
the int64_t typedef included? I see it in <stdint.h> on one compiler
I have, and <native.h> on another. I don't see these headers being
included by other standard headers on these systems.

stdint.h is part of the C99 standard. Unfortunately most implementations
do not fully meet C99. However, it is simple to write an stdint.h for
any systems that don't have it.
 
E

Eric Sosman

Kenneth said:
Is there any way to know if there is a typedef of a given name?

Not directly, no.
Specifically, I need to know if the compiler has a 64-bit integer type,
and need to know if "int64_t" exists. Something like this pseudo-code:

#if typedef(int64_t)
typedef int64_t MY_BIG_INT
#elif typedef(long long)
typedef long long MY_BIG_INT
#else
typedef long MY_BIG_INT
#endif

(Yes, this program needs to work on systems which don't have a 64-bit
integers, and it needs to take advantage of them if they are there.)

`#if __STDC_VERSION__ >= 199901L' means "C99 or later"
and implies the existence of the <stdint.h> header. Having
included this header, you can then check for the presence
of macros like INT64_MAX or UINT_LEAST64_MAX (depending on
whether you want signed or unsigned, exactly or at least 64
bits).

If you don't have C99, you still might be lucky: Some C90
implementations provide a 64-bit `long'. You can check by
including <limits.h> and inspecting the values of LONG_MAX
and/or ULONG_MAX (with care; see below).

Finally, some pre-C99 implementations provide `long long'
if invoked in a non-conforming mode. If yours does so and if
it supports `long long' in the C99 style, <limits.h> will
define LLONG_MAX and ULLONG_MAX for you to check.

Putting it all together, you'd get something like this
(the indirect value tests cater to C90 preprocessors, which
might not be able to parse longer-than-`long' numbers):

#if __STDC_VERSION__ >= 199901L
#include <stdint.h>
#ifdef INT_LEAST64_MAX
typedef int_least64_t MyBigInt;
#define MYBIGBITS 64
#endif
#endif

#ifndef MYBIGBITS
#include <limits.h>
#if (LONG_MAX >> 31) >> 31 >= 1
typedef long MyBigInt;
#define MYBIGBITS 64
#elif (LLONG_MAX >> 31) >> 31 >= 1
/* non-conforming but helpful C90 */
typedef long long MyBigInt;
#define MYBIGBITS 64
#else
/* oh, well -- better luck next time */
typedef long MyBigInt;
#define MYBIGBITS 32
#endif
#endif
Also, what is the standard include file which would be needed to have
the int64_t typedef included? I see it in <stdint.h> on one compiler
I have, and <native.h> on another. I don't see these headers being
included by other standard headers on these systems.

C99 specifies <stdint.h> but not <native.h>. C90 specifies
neither, so don't try to #include it until you've established
that you've got a C99 implementation.
 
K

Kenneth Brody

Eric Sosman wrote:
[...]
`#if __STDC_VERSION__ >= 199901L' means "C99 or later"
and implies the existence of the <stdint.h> header. Having
included this header, you can then check for the presence
of macros like INT64_MAX or UINT_LEAST64_MAX (depending on
whether you want signed or unsigned, exactly or at least 64
bits).
[...]

Thanks for the pointers.

However, what happens when __STDC_VERSION__ isn't defined at all? (I
suppose this obviously means "not C99".) Neither "cc" under SCO Unix,
nor MSVC 6.0 define this. (I haven't tried any other platforms yet.)

That's 2 underscores, "STDC", one underscore, "VERSION", two underscores.
Correct?

In any case, I'm going to be stuck with "yet another config item", as it
doesn't look like all the systems we run on have enough to automatically
determine it.

--
+-------------------------+--------------------+-----------------------------+
| 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]>
 
E

Eric Sosman

Kenneth said:
Eric Sosman wrote:
[...]
`#if __STDC_VERSION__ >= 199901L' means "C99 or later"
and implies the existence of the <stdint.h> header. Having
included this header, you can then check for the presence
of macros like INT64_MAX or UINT_LEAST64_MAX (depending on
whether you want signed or unsigned, exactly or at least 64
bits).

[...]

Thanks for the pointers.

However, what happens when __STDC_VERSION__ isn't defined at all? (I
suppose this obviously means "not C99".) Neither "cc" under SCO Unix,
nor MSVC 6.0 define this. (I haven't tried any other platforms yet.)

An identifier that isn't defined as a macro evaluates
as zero for the purposes of #if. 6.10.1/2:

"[...] After all replacements due to macro expansion
and the defined unary operator have been performed,
all remaining identifiers are replaced with the pp-
number 0, [...]"

(Personally, I wish the ANSI committee had not defined the
language this way; the "anything unrecognized is zero" rule
makes spellnig errors potentially more damaging. However,
that particular horse is no longer proximal to the barn.)
That's 2 underscores, "STDC", one underscore, "VERSION", two underscores.
Correct?

Correct. See 6.10.8/1.
 
K

Kenneth Brody

Eric said:
Kenneth said:
Eric Sosman wrote:
[...]
`#if __STDC_VERSION__ >= 199901L' means "C99 or later"
[...]
However, what happens when __STDC_VERSION__ isn't defined at all? (I
suppose this obviously means "not C99".) Neither "cc" under SCO Unix,
nor MSVC 6.0 define this. (I haven't tried any other platforms yet.)

An identifier that isn't defined as a macro evaluates
as zero for the purposes of #if. 6.10.1/2:

Well, that helps for "#if __STDC_VERSION__ >= 199901L", but it doesn't
help my test of printf("%ld\n",__STDC_VERSION__);. ;-)

[...]
Correct. See 6.10.8/1.

Thanks. I just wanted to make sure I didn't have a typo.

--
+-------------------------+--------------------+-----------------------------+
| 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]>
 
C

CBFalconer

Kenneth said:
Eric said:
Kenneth said:
Eric Sosman wrote:
[...]

`#if __STDC_VERSION__ >= 199901L' means "C99 or later" [...]
However, what happens when __STDC_VERSION__ isn't defined at all?
(I suppose this obviously means "not C99".) Neither "cc" under
SCO Unix, nor MSVC 6.0 define this. (I haven't tried any other
platforms yet.)

An identifier that isn't defined as a macro evaluates
as zero for the purposes of #if. 6.10.1/2:

Well, that helps for "#if __STDC_VERSION__ >= 199901L", but it
doesn't help my test of printf("%ld\n",__STDC_VERSION__);. ;-)

[...]
Correct. See 6.10.8/1.

Thanks. I just wanted to make sure I didn't have a typo.

You need these gyrations to investigate, since __STDC_VERSION__ is
not mentioned in C89:

#include <stdio.h>

int main(void)
{
#ifdef __STDC__
printf("__STDC__ = %d\n", __STDC__);
# ifdef __STDC_VERSION__
printf("__STDC_VERSION__ = %ld\n", __STDC_VERSION__);
# else
printf("__STDC_VERSION__ undefined\n");
# endif
#else
printf("__STDC__ undefined\n");
#endif
return 0;
}
 

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,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top