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

L

luke

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
 
A

Alexei A. Frounze

luke said:
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
 
J

Jirka Klaue

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
 
E

Eric Sosman

Alexei said:
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.

You're right about the overflow, but wrong about the
result: the behavior is undefined, and there is no guarantee
that any value (wright or rong) will be produced. The suggested
fix is correct.
 
L

luke

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
 
A

Alexei A. Frounze

Eric Sosman said:
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.
You're right about the overflow, but wrong about the
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
 
L

Lawrence Kirby

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
 
E

Eric Sosman

Alexei A. Frounze wrote On 09/21/05 10:05,:
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.
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.
 
P

Peter Nilsson

Alexei said:
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top