T.R | Title | User | Personal Name | Date | Lines |
---|
2093.1 | Unsigned arithmetic strikes again | WIBBIN::NOYCE | Pulling weeds, pickin' stones | Thu Feb 13 1997 14:21 | 15 |
| > (0 - sizeof(x))
Since sizeof() returns some unsigned integer type, this expression
is evaluated by converting 0 to the same unsigned type, and then
subtracting. Because unsigned arithmetic wraps, you get a large
positive result. On VMS, sizeof() returns unsigned int, so you
get a value of 0xFFFFFFFC, or 4294967292. Dividing by 100 gives
42949672, which is what you got. (On Digital UNIX, where sizeof()
returns unsigned long, you would have gotten a result about 4 billion
times larger.
Similarly, (0 - sizeof(x)) / -100 computes the dividend as above,
and then converts the -100 to the unsigned type, ending up with
4294967292 / 4294967196
which is 1.
|
2093.2 | Note collision; a little more detail | DECCXL::WIBECAN | That's the way it is, in Engineering! | Thu Feb 13 1997 14:33 | 64 |
| The sizeof operator return type is size_t, which on DEC C is unsigned int. An
integer expression with an unsigned int in it is converted to unsigned. (The
documentation I have explains this in section 6.10.1.2 of the DEC C Language
Reference Manual; I'll post the sections below.) This conversion affects the
results.
Case by case:
(0 - sizeof(x)) / 100 ==> (0 - 4u) / 100 ==> 4294967292 / 100 ==> 42949672
(10 - sizeof(x)) / 100 ==> (10 - 4u) / 100 ==> 6 / 100 ==> 0
(0 - sizeof(x)) / -100 ==> (0 - 4u) / -100 ==> 4294967292u / 4294967196u
==> 1
If you use a cast, e.g. "(0 - (int) sizeof(x)) / 100;" in the first example,
you'll get the results you expect (0 in all cases).
Section 6.10.1.2 from the LRM:
6.10.1.2 Signed and Unsigned Integers
Conversions also take place between the various kinds of
integers.
When a value with an integral type is converted to another
integral type (such as int converted to long int ) and the value
can be represented by the new type, the value is unchanged.
When a signed integer is converted to an unsigned integer
of equal or greater size, and the signed integer value is non-
negative, its value is unchanged. If the signed integer value is
negative, then:
� If the unsigned integer type is larger, the signed integer
is first promoted to the signed integer that corresponds
to the unsigned integer; then the value is converted to
unsigned by adding to it one greater than the largest
number that can be represented in the unsigned integer
type.
� If the unsigned integer type is equal or smaller than
the signed integer type, then the value is converted to
unsigned by adding to it one greater than the largest
number that can be represented in the unsigned integer
type.
When an integer value is demoted to an unsigned integer of
smaller size, the result is the nonnegative remainder of the
value divided by the number one greater than the largest
representable unsigned value for the new integral type.
When an integer value is demoted to a signed integer of
smaller size, or an unsigned integer is converted to its corre-
sponding signed integer, the value is unchanged if it is small
enough to be represented by the new type. Otherwise, the re-
sult is truncated; excess high-order bits are discarded and
precision is lost.
Conversion between integral types of the same size, whether
signed or unsigned, results in no machine-level representa-
tion change.
|
2093.3 | In PRE- ANSI C compilers sizeof returns an int | DECC::VMCCUTCHEON | | Thu Feb 13 1997 14:33 | 13 |
| Hi,
I believe that older C compilers like VAX C will return
a signed integer type from size_of, but in ANSI C,
size_of returns the type size_t which is an unsigned type.
So in ANSI C, the expression (0-sizeof(x)/100 is calculated
with unsigned arithmetic.
so try casting the returned value to an int, or compile /stand=vaxc
int x;
x = (0 - (signed int)sizeof(x)) / 100;
--val
|
2093.4 | Thanx! :-) | CSC32::EHA | Flip | Wed Feb 19 1997 10:50 | 5 |
| Thank you very much. They were all perfect answers for the customer.
I had an idea it was something like this, but wasn't sure where to
look.
Al
|