[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c

Preprocessor integer arithmetic

Barry Briggs

7/1/2011 1:02:00 PM

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.
3 Answers

James Kuyper

7/1/2011 1:12:00 PM

0

On 07/01/2011 09:01 AM, Noob wrote:
> 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.
--
James Kuyper

Barry Briggs

7/1/2011 1:56:00 PM

0

James Kuyper wrote:

> On 07/01/2011 09:01 AM, Noob wrote:
>> 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.

Right.

>> 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.

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.

Tim Rentsch

7/4/2011 12:42:00 AM

0

Noob <root@127.0.0.1> writes:

> 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.