Tom Lane <tgl@sss.pgh.pa.us> writes:
> Ian Lance Taylor <ian@airs.com> writes:
> > A safe way to construct a long long constant is to do it using an
> > expression:
> > ((((uint64) 0xdeadbeef) << 32) | (uint64) 0xfeedface)
> > It's awkward, obviously, but it works with any compiler.
>
> An interesting example. That will work as intended if and only if the
> compiler regards 0xfeedface as unsigned --- if the constant is initially
> treated as a signed int, then extension to 64 bits will propagate the
> wrong bit value into the high-order bits.
>
> Indeed, according to the ANSI C spec, 0xfeedface *should* be regarded as
> unsigned in a machine whose ints are 32 bits. However, this conclusion
> comes from the exact same paragraph that AIX got wrong to begin with.
> I'm not sure that doing it this way actually affords any extra protection
> against compilers that can't be trusted to handle integral constants
> per-spec...
True, for additional safety, do this: ((((uint64) (unsigned long) 0xdeadbeef) << 32) | (uint64) (unsigned long)
0xfeedface)
Of course, this won't work if long is 64 bits and int is 32 bits and
the compiler erroneously makes a hexidecimal constant signed int
rather than unsigned int, signed long (incorrect but possible), or
unsigned long.
I seem to recall that even K&R compilers support an L suffix to
indicate a long value. If that is the case, then I think this is
always safe for any compiler: ((((uint64) (unsigned long) 0xdeadbeefL) << 32) | (uint64) (unsigned long)
0xfeedfaceL)
(In reality that should certainly be safe, because there are no K&R
compilers which support a 64 bit integer type.)
Ian