Preprocessor integer arithmetic

N

Noob

Hello,

I'm using the classic...

#define VERSION_ID(major, minor, rev) ((major << 16) + (minor << 8) + rev)

#if CURRENT_VERSION > VERSION_ID(3,8,1)
/*** DO SOMETHING ***/
#else
/*** DO ANOTHER THING ***/
#endif

As it is, I need the pre-processor to handle arithmetic
on integers wider than 16 bits.

I have a nagging feeling that some implementations may
be limited to 16 bits integers, but I couldn't find
anything after a quick scan of the C90 draft.

What are the guarantees for integer arithmetic by the
pre-processor? Can it handle up to 32-bit integers?
64-bit integers?

Which section handles these details?
3.8 PREPROCESSING DIRECTIVES ?

Regards.
 
J

James Kuyper

Hello,

I'm using the classic...

#define VERSION_ID(major, minor, rev) ((major << 16) + (minor << 8) + rev)

#if CURRENT_VERSION > VERSION_ID(3,8,1)
/*** DO SOMETHING ***/
#else
/*** DO ANOTHER THING ***/
#endif

As it is, I need the pre-processor to handle arithmetic
on integers wider than 16 bits.

I have a nagging feeling that some implementations may
be limited to 16 bits integers, but I couldn't find
anything after a quick scan of the C90 draft.

What are the guarantees for integer arithmetic by the
pre-processor? Can it handle up to 32-bit integers?
64-bit integers?

In C99, preprocessor arithmetic is required to be performed in intmax_t
or uintmax_t, depending upon the sign of the integer literals involved.
Both of those types are required to be at least 64 bits.

I'm not sure precisely what the C90 standard said about this, but it
would not have mandated more than 32 bits.
Which section handles these details?
3.8 PREPROCESSING DIRECTIVES ?

In C99, it's section 6.10.1, Conditional Inclusion

If you're looking at a document which says that section 3.8 is
"PREPROCESSING DIRECTIVES", you're probably looking at the C89 draft
ANSI standard, not the C90 draft ISO standard. When adopted as an ISO
standard, three additional sections were added at the beginning to
conform with ISO requirements, so all of the other section numbers got
increased by 3.
 
N

Noob

James said:
In C99, preprocessor arithmetic is required to be performed in intmax_t
or uintmax_t, depending upon the sign of the integer literals involved.
Both of those types are required to be at least 64 bits.

I'm not sure precisely what the C90 standard said about this, but it
would not have mandated more than 32 bits.
Right.


In C99, it's section 6.10.1, Conditional Inclusion

If you're looking at a document which says that section 3.8 is
"PREPROCESSING DIRECTIVES", you're probably looking at the C89 draft
ANSI standard, not the C90 draft ISO standard. When adopted as an ISO
standard, three additional sections were added at the beginning to
conform with ISO requirements, so all of the other section numbers got
increased by 3.

Right again; what I have is an ANSI C89 draft.

"3.8.1 Conditional inclusion" states

"After all replacements are finished, the resulting preprocessing
tokens are converted into tokens, and then all remaining identifiers
are replaced with 0 . The resulting tokens comprise the controlling
constant expression which is evaluated according to the rules of $3.4
using arithmetic that has at least the ranges specified in $2.2.4.2,
except that int and unsigned int act as if they have the same
representation as, respectively, long and unsigned long . This
includes interpreting character constants, which may involve
converting escape sequences into execution character set members.
Whether the numeric value for these character constants matches the
value obtained when an identical character constant occurs in an
expression (other than within a #if or #elif directive) is
implementation-defined./75/ Also, whether a single-character character
constant may have a negative value is implementation-defined."

"3.4 CONSTANT EXPRESSIONS"
"2.2.4.2 Numerical limits" defines <limits.h>

If I understand the quoted paragraph correctly, preprocessor
integer arithmetic will be carried out with longs and/or
unsigned longs; is that right? Therefore, I'm safe up to 32 bits,
and my 24-bit macro is portable.

Regards.
 
T

Tim Rentsch

Noob said:
Hello,

I'm using the classic...

#define VERSION_ID(major, minor, rev) ((major << 16) + (minor << 8) + rev)

#if CURRENT_VERSION > VERSION_ID(3,8,1)
/*** DO SOMETHING ***/
#else
/*** DO ANOTHER THING ***/
#endif

As it is, I need the pre-processor to handle arithmetic
on integers wider than 16 bits.

I have a nagging feeling that some implementations may
be limited to 16 bits integers, but I couldn't find
anything after a quick scan of the C90 draft.

What are the guarantees for integer arithmetic by the
pre-processor? Can it handle up to 32-bit integers?
64-bit integers? [snip]

If you want to be safe, and as a matter of good style, force
the values in question to be 'unsigned long'. Because these
expressions will be used in preprocessor directives, rather
than using casting a value is forced to be (at least)
unsigned long by adding 0UL to it:

#define UL(x) ((x) + 0UL)
#define VERSION_ID(major,minor,revision) \
( (UL(major) << 16) + (UL(minor) << 8) + UL(revision) )

The range of unsigned long must be at least 32 bits, which
should be enough for the use described.
 

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