Fun with numbers - dammit, but I want a cast!

Bengt Richter bokr at oz.net
Mon Aug 11 21:23:43 EDT 2003


On Mon, 11 Aug 2003 23:46:38 GMT, Carl Banks <imbosol at aerojockey.com> wrote:

>Terry Reedy wrote:
>> No, quite different.  A C cast (at least usually) recasts a block of
>> bits in a new role without changing the bits.
>
>Certainly not.  Most type casts actually change bits.  For example,
>supposing floats and longs are both 32 bits, the expression (float)1L
>will *not* return the floating point number with the same bit pattern
>as 1L.  It returns 1.0.
>
>Usually, the only casts that preserve the bit pattern are integer to
>pointer casts, and the C standard doesn't even guarantee that (unless
>C 2000 changed it).  In fact, the C standard says (or used to say)
>that 0 must always cast to a null pointer, even if the system
>represents integer 0 and null pointer with different bits, which does
>(or used to) happen.
>
>
>IMO, a type cast is just a fancy name for an operator that takes an
>object and returns an object with the same "value" (whatever that
>means) but a different type.  In C, type casting happens to have a
>funny syntax.  In Python, it does not.  If someone asked, "does Python
>have type casting?", I would say yes, except there's no special syntax
>for it.  Rather, type casting is done by the calling type objects
>themselves.
>

Well, there is one way to look at existing bits exactly as they are in
terms of an alternate type representation. The easy way is to do reinterpret cast
on a pointer to change a pointer to the old type into a pointer to a new type,
without changing location. E.g., how else to print out the bit representation
of something? E.g., here's a hack to see floats and doubles as little-ending python strings:

====< castf.c >======================================
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]){
    float f4;
    double f8;
    int i;
    if(argc<2){ printf("Usage: castf <floating point number for atof>\n"); return 0;}
    f8 = atof(argv[1]); f4=f8;
    printf("\"");
    for(i=0; i<sizeof(f4); ++i){ printf("\\x%02x",((unsigned char *)(&f4))[i]);};
    printf("\"\n");
    printf("\"");
    for(i=0; i<sizeof(f8); ++i){ printf("\\x%02x",((unsigned char *)(&f8))[i]);};
    printf("\"\n");
    return 0;
}
=====================================================
[18:04] C:\pywk\clp>castf
Usage: castf <floating point number for atof>

[18:04] C:\pywk\clp>castf 1.625
"\x00\x00\xd0\x3f"
"\x00\x00\x00\x00\x00\x00\xfa\x3f"

[18:04] C:\pywk\clp>castf -1.625
"\x00\x00\xd0\xbf"
"\x00\x00\x00\x00\x00\x00\xfa\xbf"

[18:04] C:\pywk\clp>castf 0
"\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00"

[18:04] C:\pywk\clp>castf 1
"\x00\x00\x80\x3f"
"\x00\x00\x00\x00\x00\x00\xf0\x3f"

[18:04] C:\pywk\clp>castf -1
"\x00\x00\x80\xbf"
"\x00\x00\x00\x00\x00\x00\xf0\xbf"

Actually, it's a little confusing to look at numbers in that order, especially
since the hex for the bits in the bytes is big-end-on-the-left ;-)

2**54-1 (naturally I used python to get the number ;-)
[18:12] C:\pywk\clp>castf 18014398509481983
"\x00\x00\x80\x5a"
"\xff\xff\xff\xff\xff\xff\x4f\x43"

2**53-1
[18:12] C:\pywk\clp>castf 9007199254740991
"\x00\x00\x00\x5a"
"\xff\xff\xff\xff\xff\xff\x3f\x43"

2**52-2**12
[18:12] C:\pywk\clp>castf 9007199254736896
"\x00\x00\x00\x5a"
"\x00\xf0\xff\xff\xff\xff\x3f\x43"
   ^^   ^-bits 8-11 (the f is bits 12-15)
   ^^-bits 0-7

Of course, the cleaner way would have been to factor that instead of cutting and pasting:
Some architectures might not like addressing arbitrary bytes, but we'll leave that as exercise
material ;-)

====< castf.c >======================================
#include <stdio.h>
#include <stdlib.h>

void prnch(void *pthing, int n){
    int i;
    printf("\"");
    for(i=0; i<n; ++i){ printf("\\x%02x",((unsigned char *)(pthing))[i]);};
    printf("\"\n");
}

int main(int argc, char *argv[]){
    float f4; double f8;
    if(argc<2){ printf("Usage: castf <floating point number for atof>\n"); return 0;}
    f8 = atof(argv[1]); f4=f8;
    prnch(&f4, sizeof(f4));
    prnch(&f8, sizeof(f8));
    return 0;
}
==========================================
Regards,
Bengt Richter




More information about the Python-list mailing list