# Constants: when to use L U UL ....

Discussion in 'C Programming' started by luke, Sep 21, 2005.

1. ### lukeGuest

Hi,
I know that the suffixes L U UL mean that the constant has to be
treated as long, unsigned,... but I didn't know when to use it and when
not.
thanks

luke

luke, Sep 21, 2005

2. ### Alexei A. FrounzeGuest

"luke" <> wrote in message
news:...
> Hi,
> I know that the suffixes L U UL mean that the constant has to be
> treated as long, unsigned,... but I didn't know when to use it and when
> not.
> thanks

A few examples:

1. long x = 0xFFFF;
2. int a=10000; long c = a*4;

1.: On a 16-bit system (int is 16-bit long) you'll get x=-1, while on 32-bit
one you'll get x=65535... The fix is to write 0xFFFFU or 0xFFFFUL.
2.: On a 16-bit system you'll get an overflow in multiplication and hence
wrong value in c (less than 32768), while on 32-bit the result will be OK.
The fix is to cast either of multipliers to long or to turn 4 into 4L.

Alex

Alexei A. Frounze, Sep 21, 2005

3. ### Jirka KlaueGuest

Alexei A. Frounze:

> 1. long x = 0xFFFF;
> 2. int a=10000; long c = a*4;
>
> 1.: On a 16-bit system (int is 16-bit long) you'll get x=-1

I don't think so. Since 0xffff is in the range of unsigned int on
a 16-bit-int system, you should get 65535.

Jirka

Jirka Klaue, Sep 21, 2005
4. ### Eric SosmanGuest

Alexei A. Frounze wrote:

> "luke" <> wrote in message
> news:...
>
>>Hi,
>>I know that the suffixes L U UL mean that the constant has to be
>>treated as long, unsigned,... but I didn't know when to use it and when
>>not.
>>thanks

>
>
> A few examples:
>
> 1. long x = 0xFFFF;
> 2. int a=10000; long c = a*4;
>
> 1.: On a 16-bit system (int is 16-bit long) you'll get x=-1, while on 32-bit
> one you'll get x=65535... The fix is to write 0xFFFFU or 0xFFFFUL.

No, x will be 65535 on all conforming C implementations.
On a system with 16-bit int, 0xFFFF is an unsigned int constant
with the value 65535u. On a system with wider int, 0xFFFF is
an int constant with the value 65535. Either way, x is initialized
with the value 65535(u), converted to long. See 6.4.4.1/5.

> 2.: On a 16-bit system you'll get an overflow in multiplication and hence
> wrong value in c (less than 32768), while on 32-bit the result will be OK.
> The fix is to cast either of multipliers to long or to turn 4 into 4L.

result: the behavior is undefined, and there is no guarantee
that any value (wright or rong) will be produced. The suggested
fix is correct.

--
Eric Sosman
lid

Eric Sosman, Sep 21, 2005
5. ### lukeGuest

thanx for the answer, but I didn't understand why "long x = 0xFFFF"
produces -1
a long is 32 bit even on 16-bit systems, isn't it? so you get 65535
anyway

luke, Sep 21, 2005
6. ### Alexei A. FrounzeGuest

"Eric Sosman" <> wrote in message
news:...
> Alexei A. Frounze wrote:
> > 1. long x = 0xFFFF;
> > 2. int a=10000; long c = a*4;
> >
> > 1.: On a 16-bit system (int is 16-bit long) you'll get x=-1, while on

32-bit
> > one you'll get x=65535... The fix is to write 0xFFFFU or 0xFFFFUL.

>
> No, x will be 65535 on all conforming C implementations.
> On a system with 16-bit int, 0xFFFF is an unsigned int constant
> with the value 65535u. On a system with wider int, 0xFFFF is
> an int constant with the value 65535. Either way, x is initialized
> with the value 65535(u), converted to long. See 6.4.4.1/5.

OK, I was wrong. But I remember I had some problem with this or something
very similar... But maybe it was a bit different thing (signed to unsigned
conversion), though...
Sorry.

> > 2.: On a 16-bit system you'll get an overflow in multiplication and

hence
> > wrong value in c (less than 32768), while on 32-bit the result will be

OK.
> > The fix is to cast either of multipliers to long or to turn 4 into 4L.

>
> result: the behavior is undefined, and there is no guarantee
> that any value (wright or rong) will be produced. The suggested
> fix is correct.

You're right about the UB (as prescribed by the standard), though it's more
likely to get this problem w/o any side effects other than just a wrong
value. Actually, I'd probably prefer to get an exception as form of this UB
to locate the problematic place in the code.

Alex

Alexei A. Frounze, Sep 21, 2005
7. ### Lawrence KirbyGuest

On Wed, 21 Sep 2005 06:01:23 -0700, luke wrote:

> thanx for the answer, but I didn't understand why "long x = 0xFFFF"
> produces -1

It doesn't.

> a long is 32 bit even on 16-bit systems, isn't it? so you get 65535
> anyway

However 0xFFFF doesn't have long type, it has type int of that can
represent 65535 or else unsigned int which is guaranteed to be able to
represent 65535. In either case the value is then converted to long before
being assigned.

So the code does do the right thing i.e. x ends up with the value 65535,
always. But there are types other than long involved. However

long x = 0x10000;

STILL works find and is guaranteed to give x the value 65536. If the value
can't be represented as an unsigned int the compiler will represent it as
a long. However there are cases where you need to force to a longer type,
e.g. the expression

1 << 24

i.e. 1 left shifted 24 places is invalid on systems with, say, 16 bit
ints. Whereas

1L << 24

and for many cases

1UL << 24

is even better because bit manipulations are best done on unsigned types.

Lawrence

Lawrence Kirby, Sep 21, 2005
8. ### Eric SosmanGuest

Alexei A. Frounze wrote On 09/21/05 10:05,:
> "Eric Sosman" <> wrote in message
> news:...
>
>>Alexei A. Frounze wrote:
>>
>>>1. long x = 0xFFFF;
>>>2. int a=10000; long c = a*4;
>>>
>>>1.: On a 16-bit system (int is 16-bit long) you'll get x=-1, while on

>
> 32-bit
>
>>>one you'll get x=65535... The fix is to write 0xFFFFU or 0xFFFFUL.

>>
>> No, x will be 65535 on all conforming C implementations.
>>On a system with 16-bit int, 0xFFFF is an unsigned int constant
>>with the value 65535u. On a system with wider int, 0xFFFF is
>>an int constant with the value 65535. Either way, x is initialized
>>with the value 65535(u), converted to long. See 6.4.4.1/5.

>
>
> OK, I was wrong. But I remember I had some problem with this or something
> very similar... But maybe it was a bit different thing (signed to unsigned
> conversion), though...
> Sorry.

On many 16-bit systems, `long x = (int)0xFFFF;' would
initialize x to -1. More plausibly,

int i = 0xFFFF;
long x = i;

is likely (but not guaranteed, of course) to do the same.

>>>2.: On a 16-bit system you'll get an overflow in multiplication and

>
> hence
>
>>>wrong value in c (less than 32768), while on 32-bit the result will be

>
> OK.
>
>>>The fix is to cast either of multipliers to long or to turn 4 into 4L.

>>
>>result: the behavior is undefined, and there is no guarantee
>>that any value (wright or rong) will be produced. The suggested
>>fix is correct.

>
>
> You're right about the UB (as prescribed by the standard), though it's more
> likely to get this problem w/o any side effects other than just a wrong
> value. Actually, I'd probably prefer to get an exception as form of this UB
> to locate the problematic place in the code.

IIRC (it was long ago), the IBM s/360 could be operated in
a mode that produced traps when integer arithmetic overflowed.
I don't know whether that mode survives in its s/390 -- er,
excuse me, "eServer zSeries" descendant.

--

Eric Sosman, Sep 21, 2005
9. ### Peter NilssonGuest

Alexei A. Frounze wrote:
> "luke" <> wrote in message
> news:...
> > Hi,
> > I know that the suffixes L U UL mean that the constant has to be
> > treated as long, unsigned,... but I didn't know when to use it and when
> > not.
> > thanks

>
> A few examples:
>
> 1. long x = 0xFFFF;
> 2. int a=10000; long c = a*4;

<snip>

Here you should use 4L instead of 4 as the expression a*4 is
calculating
using int arithmetic. If int is 16-bit, then c may not get the value
40000.

--
Peter

Peter Nilsson, Sep 22, 2005