Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #19121 > unrolled thread

what would be the most portable way to test if UINT_MAX>=0xFFFFFFF with the preprocessor?

Started byFrancois Grieu <fgrieu@gmail.com>
First post2012-03-28 22:34 +0200
Last post2012-04-03 18:15 +0200
Articles 8 — 5 participants

Back to article view | Back to comp.lang.c


Contents

  what would be the most portable way to test if UINT_MAX>=0xFFFFFFF with the preprocessor? Francois Grieu <fgrieu@gmail.com> - 2012-03-28 22:34 +0200
    Re: what would be the most portable way to test if UINT_MAX>=0xFFFFFFF with the preprocessor? Tim Rentsch <txr@alumni.caltech.edu> - 2012-03-28 14:47 -0700
      Re: what would be the most portable way to test if UINT_MAX>=0xFFFFFFF with the preprocessor? Francois Grieu <fgrieu@gmail.com> - 2012-03-29 07:49 +0200
        Re: what would be the most portable way to test if UINT_MAX>=0xFFFFFFF with the preprocessor? Tim Rentsch <txr@alumni.caltech.edu> - 2012-03-28 23:51 -0700
        Re: what would be the most portable way to test if UINT_MAX>=0xFFFFFFF with the preprocessor? Jens Gustedt <jens.gustedt@loria.fr> - 2012-03-29 17:21 +0200
    Re: what would be the most portable way to test if UINT_MAX>=0xFFFFFFF with the preprocessor? ImpalerCore <jadill33@gmail.com> - 2012-03-28 14:14 -0700
    Re: what would be the most portable way to test if UINT_MAX>=0xFFFFFFF with the preprocessor? China Blue Water Navy <chine.bleu@yahoo.com> - 2012-04-02 15:04 -0700
      Re: what would be the most portable way to test if UINT_MAX>=0xFFFFFFF with the preprocessor? Francois Grieu <fgrieu@gmail.com> - 2012-04-03 18:15 +0200

#19121 — what would be the most portable way to test if UINT_MAX>=0xFFFFFFF with the preprocessor?

FromFrancois Grieu <fgrieu@gmail.com>
Date2012-03-28 22:34 +0200
Subjectwhat would be the most portable way to test if UINT_MAX>=0xFFFFFFF with the preprocessor?
Message-ID<4f7375a7$0$719$426a74cc@news.free.fr>
I have code on the tune of

#include <limits.h>

#if 0xFFFFFFFF>=UINT_MAX
     typedef unsigned int    tu32;   /* unsigned at-least-32-bit type */
     #define P_TU32          ""      /* printf prefix for tu32 (none) */
#else
     typedef unsigned long   tu32;   /* unsigned at-least-32-bit type */
     #define P_TU32          "l"     /* printf prefix for tu32 */
#endif


It works on all current versions of compilers I use (one of which is 8
years old, and many claim only C89 compatibility, plus a few extensions
like // comments).

However, I am concerned that when UINT_MAX is 0xFFFF, some old preprocessors
might evaluate 0xFFFFFFFF>=0xFFFF as if it was -1>=0xFFFF, and thus take the
wrong branch. From memory, this has hit me once, though I can't pinpoint a
culprit.

Does one know a compiler/preprocessor where #if 0xFFFFFFFF>=UINT_MAX would
not work correctly?

What would be the safest way?  What about #if UINT_MAX>>30 >= 3  ?


TIA,

   Francois Grieu

[toc] | [next] | [standalone]


#19124

FromTim Rentsch <txr@alumni.caltech.edu>
Date2012-03-28 14:47 -0700
Message-ID<kfnaa30iej3.fsf@x-alumni2.alumni.caltech.edu>
In reply to#19121
Francois Grieu <fgrieu@gmail.com> writes:

> I have code on the tune of
>
> #include <limits.h>
>
> #if 0xFFFFFFFF>=UINT_MAX
>     typedef unsigned int    tu32;   /* unsigned at-least-32-bit type */
>     #define P_TU32          ""      /* printf prefix for tu32 (none) */
> #else
>     typedef unsigned long   tu32;   /* unsigned at-least-32-bit type */
>     #define P_TU32          "l"     /* printf prefix for tu32 */
> #endif

It looks like the comparison in the #if is turned around.  Am I
misunderstanding what you're trying to do?

> It works on all current versions of compilers I use (one of which is 8
> years old, and many claim only C89 compatibility, plus a few extensions
> like // comments).
>
> However, I am concerned that when UINT_MAX is 0xFFFF, some old preprocessors
> might evaluate 0xFFFFFFFF>=0xFFFF as if it was -1>=0xFFFF, and thus take the
> wrong branch. From memory, this has hit me once, though I can't pinpoint a
> culprit.
>
> Does one know a compiler/preprocessor where #if 0xFFFFFFFF>=UINT_MAX would
> not work correctly?
>
> What would be the safest way?  What about #if UINT_MAX>>30 >= 3  ?

I would probably use   -1U >> 15 >> 15  >= 3

It's possible that the shift of 30 is guaranteed to
work in #if because of special rules for how arithmetic
is done in the preprocessor, but I'm not sure older
compilers should be trusted to get that right (even
assuming the guarantee holds, which I'm not sure it
does for C89/C90).

Also, using two shifts of only 15 each means the same
expression can be used portably in regular code and not
just the preprocessor, which obviously has a certain
amount of appeal, and also some value (eg, if this test
is made available as a macro which might be used in an
'if()' in addition to #if).

[toc] | [prev] | [next] | [standalone]


#19131

FromFrancois Grieu <fgrieu@gmail.com>
Date2012-03-29 07:49 +0200
Message-ID<4f73f7dc$0$1714$426a74cc@news.free.fr>
In reply to#19124
On 28/03/2012 23:47, Tim Rentsch wrote:
> Francois Grieu<fgrieu@gmail.com>  writes:
>
>> I have code on the tune of
>>
>> #include<limits.h>
>>
>> #if 0xFFFFFFFF>=UINT_MAX
>>      typedef unsigned int    tu32;   /* unsigned at-least-32-bit type */
>>      #define P_TU32          ""      /* printf prefix for tu32 (none) */
>> #else
>>      typedef unsigned long   tu32;   /* unsigned at-least-32-bit type */
>>      #define P_TU32          "l"     /* printf prefix for tu32 */
>> #endif
>
> It looks like the comparison in the #if is turned around.  Am I
> misunderstanding what you're trying to do?

You read my mind. The code actually contains  #if 0xFFFFFFFF<=UINT_MAX
and this mess is me trying to make it look like the title of the post.


>> It works on all current versions of compilers I use (one of which is 8
>> years old, and many claim only C89 compatibility, plus a few extensions
>> like // comments).
>>
>> However, I am concerned that when UINT_MAX is 0xFFFF, some old preprocessors
>> might evaluate 0xFFFFFFFF>=0xFFFF as if it was -1>=0xFFFF, and thus take the
>> wrong branch. From memory, this has hit me once, though I can't pinpoint a
>> culprit.
>>
>> Does one know a compiler/preprocessor where #if 0xFFFFFFFF>=UINT_MAX would
>> not work correctly?
>>
>> What would be the safest way?  What about #if UINT_MAX>>30>= 3  ?
>
> I would probably use   -1U>>  15>>  15>= 3

I think that the preprocessor part of cross-compilers is allowed
to use wider types than their target. 1U can be 64-bit as far
as the preprocessor is concerned, even if UINT_MAX is 0xFFFF,
right?

At least, I met preprocessors which perform all their arithmetic
over 32 bits, even though the compiler does not. In these
#if ( 256<<8 )         is taken
  if ( 256<<8 )         is not taken
and this is NOT a non-conformance AFAIK.

> It's possible that the shift of 30 is guaranteed to
> work in #if because of special rules for how arithmetic
> is done in the preprocessor, but I'm not sure older
> compilers should be trusted to get that right (even
> assuming the guarantee holds, which I'm not sure it
> does for C89/C90).
> Also, using two shifts of only 15 each means the same
> expression can be used portably in regular code and not
> just the preprocessor, which obviously has a certain
> amount of appeal, and also some value (eg, if this test
> is made available as a macro which might be used in an
> 'if()' in addition to #if).

Good catch.   #if UINT_MAX>>15>>15 >= 3

   Francois Grieu

[toc] | [prev] | [next] | [standalone]


#19133

FromTim Rentsch <txr@alumni.caltech.edu>
Date2012-03-28 23:51 -0700
Message-ID<kfnvclnhpco.fsf@x-alumni2.alumni.caltech.edu>
In reply to#19131
Francois Grieu <fgrieu@gmail.com> writes:

> On 28/03/2012 23:47, Tim Rentsch wrote:
>> Francois Grieu<fgrieu@gmail.com>  writes:
>>
>>> I have code on the tune of
>>>
>>> #include<limits.h>
>>>
>>> #if 0xFFFFFFFF <= UINT_MAX           /* [incorporate correction] */
>>>      typedef unsigned int    tu32;   /* unsigned at-least-32-bit type */
>>>      #define P_TU32          ""      /* printf prefix for tu32 (none) */
>>> #else
>>>      typedef unsigned long   tu32;   /* unsigned at-least-32-bit type */
>>>      #define P_TU32          "l"     /* printf prefix for tu32 */
>>> #endif
>>>
>>> It works on all current versions of compilers I use (one of which is 8
>>> years old, and many claim only C89 compatibility, plus a few extensions
>>> like // comments).
>>>
>>> However, I am concerned that when UINT_MAX is 0xFFFF, some old preprocessors
>>> might evaluate 0xFFFFFFFF>=0xFFFF as if it was -1>=0xFFFF, and thus take the
>>> wrong branch. From memory, this has hit me once, though I can't pinpoint a
>>> culprit.
>>>
>>> Does one know a compiler/preprocessor where #if 0xFFFFFFFF>=UINT_MAX would
>>> not work correctly?
>>>
>>> What would be the safest way?  What about #if UINT_MAX>>30>= 3  ?
>>
>> I would probably use   -1U >> 15 >> 15 >= 3
>
> I think that the preprocessor part of cross-compilers is allowed
> to use wider types than their target. 1U can be 64-bit as far
> as the preprocessor is concerned, even if UINT_MAX is 0xFFFF,
> right?
>
> At least, I met preprocessors which perform all their arithmetic
> over 32 bits, even though the compiler does not. In these
> #if ( 256<<8 )         is taken
>  if ( 256<<8 )         is not taken
> and this is NOT a non-conformance AFAIK.

You're right, and actually it's worse than just a cross-platform
concern -- in a preprocessor expression, -1U will have at least
32 bits regardless of the size of unsigned int.  So using
UINT_MAX is right, -1U is wrong.  Thank you for pointing out
this problem.


>> It's possible that the shift of 30 is guaranteed to
>> work in #if because of special rules for how arithmetic
>> is done in the preprocessor, but I'm not sure older
>> compilers should be trusted to get that right (even
>> assuming the guarantee holds, which I'm not sure it
>> does for C89/C90).

I went back and checked and this guarantee holds even under
C89/C90, modulo the earlier compilers getting it right of
course.
 
>> Also, using two shifts of only 15 each means the same
>> expression can be used portably in regular code and not
>> just the preprocessor, which obviously has a certain
>> amount of appeal, and also some value (eg, if this test
>> is made available as a macro which might be used in an
>> 'if()' in addition to #if).
>
> Good catch.   #if UINT_MAX>>15>>15 >= 3

Glad to be of service. :)

[toc] | [prev] | [next] | [standalone]


#19135

FromJens Gustedt <jens.gustedt@loria.fr>
Date2012-03-29 17:21 +0200
Message-ID<4F747DFC.3090800@loria.fr>
In reply to#19131
Am 03/29/2012 07:49 AM, schrieb Francois Grieu:
> I think that the preprocessor part of cross-compilers is allowed
> to use wider types than their target. 1U can be 64-bit as far
> as the preprocessor is concerned, even if UINT_MAX is 0xFFFF,
> right?
> 
> At least, I met preprocessors which perform all their arithmetic
> over 32 bits, even though the compiler does not. In these
> #if ( 256<<8 )         is taken
>  if ( 256<<8 )         is not taken
> and this is NOT a non-conformance AFAIK.

Since C99 the preprocessor arithmetic must be the one of {u}intmaxt_t
for the target platform. So your example is well possible.

The #-comparison is done in intmax_t and goes ok.

The other one is done with int. If int has only 16 bit 256<<8 is an
overflow and thus the behavior is undefined.

Jens

[toc] | [prev] | [next] | [standalone]


#19233

FromImpalerCore <jadill33@gmail.com>
Date2012-03-28 14:14 -0700
Message-ID<588dd1f9-cecf-409c-ab2a-4d69f8317f10@q11g2000vbu.googlegroups.com>
In reply to#19121
On Mar 28, 4:34 pm, Francois Grieu <fgr...@gmail.com> wrote:
> I have code on the tune of
>
> #include <limits.h>
>
> #if 0xFFFFFFFF>=UINT_MAX
>      typedef unsigned int    tu32;   /* unsigned at-least-32-bit type */
>      #define P_TU32          ""      /* printf prefix for tu32 (none) */
> #else
>      typedef unsigned long   tu32;   /* unsigned at-least-32-bit type */
>      #define P_TU32          "l"     /* printf prefix for tu32 */
> #endif
>
> It works on all current versions of compilers I use (one of which is 8
> years old, and many claim only C89 compatibility, plus a few extensions
> like // comments).
>
> However, I am concerned that when UINT_MAX is 0xFFFF, some old preprocessors
> might evaluate 0xFFFFFFFF>=0xFFFF as if it was -1>=0xFFFF, and thus take the
> wrong branch. From memory, this has hit me once, though I can't pinpoint a
> culprit.
>
> Does one know a compiler/preprocessor where #if 0xFFFFFFFF>=UINT_MAX would
> not work correctly?
>
> What would be the safest way?  What about #if UINT_MAX>>30 >= 3  ?

Maybe something along these lines?

#if (ULONG_MAX == 0xffffffffUL)
   typedef unsigned long uint32_t;
#elif (UINT_MAX == 0xffffffffUL)
   typedef unsigned int uint32_t;
#elif (USHRT_MAX == 0xffffffffUL)
   typedef unsigned short uint32_t;
#else
#  error "Platform not supported"
#endif

Best regards,
John D.

[toc] | [prev] | [next] | [standalone]


#19261

FromChina Blue Water Navy <chine.bleu@yahoo.com>
Date2012-04-02 15:04 -0700
Message-ID<chine.bleu-A0FDCB.15042702042012@news.eternal-september.org>
In reply to#19121
In article <4f7375a7$0$719$426a74cc@news.free.fr>,
 Francois Grieu <fgrieu@gmail.com> wrote:

> I have code on the tune of
> 
> #include <limits.h>
> 
> #if 0xFFFFFFFF>=UINT_MAX
>      typedef unsigned int    tu32;   /* unsigned at-least-32-bit type */
>      #define P_TU32          ""      /* printf prefix for tu32 (none) */
> #else
>      typedef unsigned long   tu32;   /* unsigned at-least-32-bit type */
>      #define P_TU32          "l"     /* printf prefix for tu32 */
> #endif
> 
> 
> It works on all current versions of compilers I use (one of which is 8
> years old, and many claim only C89 compatibility, plus a few extensions
> like // comments).
> 
> However, I am concerned that when UINT_MAX is 0xFFFF, some old preprocessors
> might evaluate 0xFFFFFFFF>=0xFFFF as if it was -1>=0xFFFF, and thus take the
> wrong branch. From memory, this has hit me once, though I can't pinpoint a
> culprit.
> 
> Does one know a compiler/preprocessor where #if 0xFFFFFFFF>=UINT_MAX would
> not work correctly?
> 
> What would be the safest way?  What about #if UINT_MAX>>30 >= 3  ?

I do the equivalent of 'make main' with

    main:   main.c local.h
        cc -o main main.c
   local.h:  local
        local >local.h
   local:  local.c
        cc -o local local.c

where local.c might include things like

    if (sizeof(int)==4) {
        if (0xFFFFFFFF>=UINT_MAX)
            printf("typedef unsigned int tu32\n#define P_TU32 \"\"\n");
        else
            printf("typedef unsigned long tu32\n#define P_TU32 \"l\"\n");
    }else
        printf("typedef unsigned long tu32\n#define P_TU32 \"l\"\n");

-- 
My name Indigo Montoya.      |    R'lyeh 38o57'6.5''S 102o51'16''E.
You flamed my father.        |       I'm whoever you want me to be.
Prepare to be spanked.       |  Annoying Usenet one post at a time.
Stop posting that!           |    At least I can stay in character.

[toc] | [prev] | [next] | [standalone]


#19280

FromFrancois Grieu <fgrieu@gmail.com>
Date2012-04-03 18:15 +0200
Message-ID<4f7b2207$0$6846$426a74cc@news.free.fr>
In reply to#19261
On 03/04/2012 00:04, China Blue Water Navy wrote:
> In article <4f7375a7$0$719$426a74cc@news.free.fr>,
>  Francois Grieu <fgrieu@gmail.com> wrote (and made some corrections):
> 
>> I have code on the tune of
>>
>> #include <limits.h>
>>
>> #if UINT_MAX>=0xFFFFFFFF // fixed!
>>      typedef unsigned int    tu32;   /* unsigned at-least-32-bit type */
>>      #define P_TU32          ""      /* printf prefix for tu32 (none) */
>> #else
>>      typedef unsigned long   tu32;   /* unsigned at-least-32-bit type */
>>      #define P_TU32          "l"     /* printf prefix for tu32 */
>> #endif
>>
>>
>> It works on all current versions of compilers I use (one of which is 8
>> years old, and many claim only C89 compatibility, plus a few extensions
>> like // comments).
>>
>> However, I am concerned that when UINT_MAX is 0xFFFF, some old preprocessors
>> might evaluate 0xFFFF>=0xFFFFFFFF as if it was 0xFFFF>=-1, and thus take the
>> wrong branch. From memory, this has hit me once, though I can't pinpoint a
>> culprit.
>>
>> Does one know a compiler/preprocessor where #if 0xFFFFFFFF>=UINT_MAX would
>> not work correctly?
>>
>> What would be the safest way?  What about #if UINT_MAX>>30 >= 3  ?
> 
> I do the equivalent of 'make main' with
> 
>     main:   main.c local.h
>         cc -o main main.c
>    local.h:  local
>         local >local.h
>    local:  local.c
>         cc -o local local.c
> 
> where local.c might include things like
> 
>     if (sizeof(int)==4) {
>         if (UINT_MAX>=0xFFFFFFFF)
>             printf("typedef unsigned int tu32\n#define P_TU32 \"\"\n");
>         else
>             printf("typedef unsigned long tu32\n#define P_TU32 \"l\"\n");
>     }else
>         printf("typedef unsigned long tu32\n#define P_TU32 \"l\"\n");
> 

One problem is: many of my target are "freestanding" environments (as
defined by ISO/IEC 9899:1999 section 4p6), thus do not have printf.
I do have check made by the compiler (at compile time) that tu32
has the correct behavior; something like:

#define ASSERT_S(cond) extern char assert__failure[0!=(cond)?1:-1];
ASSERT_S( (tu32)0-(tu32)1 == 0xFFFFFFFFL );


  Francois Grieu

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web