www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Integer promotion...

reply Oskar <Oskar_member pathlink.com> writes:
In both (32-bit int) C and D, i find working with 64 bit integer types to be
problematic because of the integer promotion rules. How would a 64-bit D handle
this? Will integer operands be promoted to 64bit?

I tripped on this today:

long a = rand()%10 - 5;
assert(a < 100); // FAILS 50% of the time

changing long -> int makes the assert valid.

I know why this happens (5 is cast into uint). It is the same way it works in C.
More cases:

ubyte test1() { return 1; }
uint  test2() { return 1; }
ulong test3() { return 1; }

void main() {
int  a = test1() - 2;
long b = test1() - 2;
int  c = test2() - 2;
long d = test2() - 2;
int  e = test3() - 2; 
long f = test3() - 2;
assert(a < 0); // OK
assert(b < 0); // OK
assert(c < 0); // OK
assert(d < 0); // FAILS
assert(e < 0); // OK
assert(f < 0); // OK
}

Is there anything I can do to help me avoid making such errors? :)

Why are integer operands converted to unsigned rather than signed when their
sizes match? (I'm sure there are good reasons.)

Is there any way to introduce a warning to help finding this problem, without
introducing warnings all over the place in old and correct code?

Also, why is there no warning at conversion from uint to int when there is from
ulong to long? Like here:

uint  test1 () { return 1; }
ulong test2 () { return 1; }

void main() {
int   a = test1() - 2;   // NO WARNING
long  b = test2() - 2L;  // WARNING: conversion ulong -> long
}

Is that because (int) = (int) + (ubyte) and similar are too common?
Aug 26 2005
parent Shammah Chancellor <Shammah_member pathlink.com> writes:
In article <denad2$1e8u$1 digitaldaemon.com>, Oskar says...
In both (32-bit int) C and D, i find working with 64 bit integer types to be
problematic because of the integer promotion rules. How would a 64-bit D handle
this? Will integer operands be promoted to 64bit?

I tripped on this today:

long a = rand()%10 - 5;
assert(a < 100); // FAILS 50% of the time

changing long -> int makes the assert valid.

I know why this happens (5 is cast into uint). It is the same way it works in C.
More cases:

ubyte test1() { return 1; }
uint  test2() { return 1; }
ulong test3() { return 1; }

void main() {
int  a = test1() - 2;
long b = test1() - 2;
int  c = test2() - 2;
long d = test2() - 2;
int  e = test3() - 2; 
long f = test3() - 2;
assert(a < 0); // OK
assert(b < 0); // OK
assert(c < 0); // OK
assert(d < 0); // FAILS
assert(e < 0); // OK
assert(f < 0); // OK
}

Is there anything I can do to help me avoid making such errors? :)

Why are integer operands converted to unsigned rather than signed when their
sizes match? (I'm sure there are good reasons.)

Is there any way to introduce a warning to help finding this problem, without
introducing warnings all over the place in old and correct code?

Also, why is there no warning at conversion from uint to int when there is from
ulong to long? Like here:

uint  test1 () { return 1; }
ulong test2 () { return 1; }

void main() {
int   a = test1() - 2;   // NO WARNING
long  b = test2() - 2L;  // WARNING: conversion ulong -> long
}

Is that because (int) = (int) + (ubyte) and similar are too common?

There was another thread about this which I think is related. It had to do with typedefs. In that issue (Stewart was the discoverer, check his recent posts.) the returned value took on the type of the left hand value. You might test this:
long d = test2() - 2;
assert(d < 0); // FAILS

---->
long d = -2 + test2();
assert(d < 0); // FAILS

-Sha
Aug 26 2005