On Thu, 3 Jan 2002, Nicholas Clark wrote:

> On Thu, Jan 03, 2002 at 08:46:31AM -0600, David M. Lloyd wrote:
>
> > Maybe we should be using the Configure output to determine what postfix to
> > use, based on the size of ints, longs, long longs, etc., and pointers,
> > rather than "almost always" being right?
>
> I don't think that we can even safely do this. I think we need explicit
> casting. Assuming that this
>
>     stacklow      => '(~0xfff)UL',
>     intlow        => '(~0xfff)UL',
>     numlow        => '(~0xfff)UL',
>     strlow        => '(~0xfff)UL',
>     pmclow        => '(~0xfff)UL',
>
> is being turned into
>
>   some_type stacklow = (~0xfff)UL.
>
> If some_type is unsigned long long, and long isn't as large as long long, then
> it will go wrong.

That's why we would use ULL, not UL.

Also, the UL[L] should probably be on the inside of the ():

    stacklow => '(~0xfffULL)',

Because otherwise I'd imagine that most C compilers would assume 'int' as
the datatype to apply the ~ to, and then cast the resultant constant to
unsigned long.

In fact, I'm surprised that seperating UL[L] from the literal constant
doesn't give a compiler error.

> Say long long is 64 bit and long is 32, you get ~0xfff evaluating to
> 0xfffff000 on the right of an assignment, and then the value
> 0x00000000fffff000 assigned to the long long. (or presumably 64 bit
> pointer). When what you really wanted was 0xfffffffffffff000.
>
> You'd need to do
>
>   some_type stacklow = ~((unsigned long long) 0xfff)
>
> I think.

You would do this:

    some_type stacklow = ~(0xfffull)

> And I believe I've encountered recent versions of gcc that don't promote to
> long long as one might expect. (I don't know what ANSI C99 says you should be
> doing, but it's actually irrelevant when there are real gccs out there that are
> doing something else)
>
> IIRC I had
>
>   unsigned long bar = something.;
>   unsigned long long foo = bar << (unsigned long long) 53;
>
> and I was expecting the << to be unsigned long long because one side was ULL.
> And bar to be promoted to unsigned long long as an argument to <<.
>
> And what gcc was doing was ignoring the ULLness of the right hand side,
> doing an unsigned long shift (which spilled off the end completely.
> oops. undefined behaviour, nevermind) and then promoting the result of
> that to long long.

To be perfectly safe, I would cast both operands:

unsigned long long foo = (unsigned long long)bar << 53ull;

- D

<[EMAIL PROTECTED]>

Reply via email to