Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #19121 > unrolled thread
| Started by | Francois Grieu <fgrieu@gmail.com> |
|---|---|
| First post | 2012-03-28 22:34 +0200 |
| Last post | 2012-04-03 18:15 +0200 |
| Articles | 8 — 5 participants |
Back to article view | Back to comp.lang.c
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
| From | Francois Grieu <fgrieu@gmail.com> |
|---|---|
| Date | 2012-03-28 22:34 +0200 |
| Subject | what 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]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-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]
| From | Francois Grieu <fgrieu@gmail.com> |
|---|---|
| Date | 2012-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]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-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]
| From | Jens Gustedt <jens.gustedt@loria.fr> |
|---|---|
| Date | 2012-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]
| From | ImpalerCore <jadill33@gmail.com> |
|---|---|
| Date | 2012-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]
| From | China Blue Water Navy <chine.bleu@yahoo.com> |
|---|---|
| Date | 2012-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]
| From | Francois Grieu <fgrieu@gmail.com> |
|---|---|
| Date | 2012-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