[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference turris::decc

Title:DECC
Notice:General DEC C discussions
Moderator:TLE::D_SMITHNTE
Created:Fri Nov 13 1992
Last Modified:Fri Jun 06 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:2212
Total number of notes:11045

2093.0. "SIZEOF returning invalid value in calculation." by CSC32::EHA (Flip) Thu Feb 13 1997 13:11

    Hello,
    
    I have a customer that is seeing a problem with the sizeof dunction
    when it is being used in an equation.  I have three small examples, one
    works and two do not.  The result should be zero.  This is run on an
    Alpha VMS 6.2 with DEC C 5.5-002 and my customer states that it is
    happening on Alpha VMS 7.1 and DEC C 5.3.
    
$ on warning then goto clean_up
$ create size.c
#include stdio
main ()
{
int x;
x = (0 - sizeof(x)) / 100;
printf(" x = %d\n", x);
}
$ create size1.c
#include stdio
main ()
{
int x;
x = (10 - sizeof(x)) / 100;
printf(" x = %d\n", x);
}
$ create size2.c
#include stdio
main ()
{
int x;
x = (0 - sizeof(x)) / -100;
printf(" x = %d\n", x);
}
$!
$ cc size
$ cc size1
$ cc size2
$!
$ link size
$ link size1
$ link size2
$!
$ run size
 x = 42949672
$ run size1
 x = 0
$ run size2
 x = 1
$!
$clean_up:
$ ver = f$verify(ver)
    
    Please note the second program differes from the first in the zero is
    changed to a 10.  The third differs from the first in that the 100 is
    now a -100.
    
    Thank you!
    Al
T.RTitleUserPersonal
Name
DateLines
2093.1Unsigned arithmetic strikes againWIBBIN::NOYCEPulling weeds, pickin' stonesThu Feb 13 1997 14:2115
> (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.2Note collision; a little more detailDECCXL::WIBECANThat's the way it is, in Engineering!Thu Feb 13 1997 14:3364
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.3In PRE- ANSI C compilers sizeof returns an intDECC::VMCCUTCHEONThu Feb 13 1997 14:3313
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.4Thanx! :-)CSC32::EHAFlipWed Feb 19 1997 10:505
    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