[plt-scheme] off (plt) topic (short koan in .c language and a question)

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Fri May 7 16:17:11 EDT 2010

I believe that Robby is correct. As of C99, the compiler is not obliged
to generate machine code that executes

    *(int *) chunk = number;

before

    f = *(float *) chunk;

because the compiler is allowed to assume that an `int *' is not
aliased to a `float *' --- and if the two pointers are not aliased,
then the order of those two statements shouldn't matter. Of course, the
point of your example is to alias them, but a C99 compiler is allowed
to assume the opposite. Recent versions of gcc will sometimes reorder
instructions on such assumptions.

If you want to see `int' bits interpreted as `float' bits reliably,
then you should do something like

 int i = ...;
 float f;

 memcpy(&f, &i, sizeof(int));


At Fri, 7 May 2010 15:01:08 -0500, Robby Findler wrote:
> Yes, thank you. I understood your program the first time. I'm saying
> that I believe it is not legal C code, due to an obscure part of the
> specification of the C programming language. Unfortunately, I cannot
> point you to a relevant version of the specification. Apologies and
> I'll just be quiet now.
> 
> Robby
> 
> On Fri, May 7, 2010 at 2:11 PM, Vladimir Konrad <vladimir at ok2home.net> wrote:
> >> On Fri, May 7, 2010 at 10:01 AM, vladimir<vladimir at ok2home.net>  wrote:
> >>>>
> >>>> even without pointers, allocation or dubious-looking type casts:
> >>>
> >>> but none of that type casts should give any warning in decent .c
> >>> compiler (on arch where size of integer equals the size of float in
> >>> bits).
> >>
> >> If I understand the spec properly (which is not clear....) then your
> >> program was illegal, but the revision was okay, since the spec (I
> >> think) says that you cannot point to the same address with two
> >> different types unless one of the types is void*.
> >
> > I think the program is valid, one can _read_ void* any way
> > one likes. The program is kinda like this:
> >
> >  print 4 bytes below as float
> >   |
> >   |
> > [XXXX]  (initialised 4 bytes - the chunk* - the actual bits,
> >   |     not the variable)
> >   |
> >  print the 4 bytes above as integer
> >
> >
> >
> > I have commented the code and at the very end there is simplification...
> >
> > (a comment above a line is about this line)
> >
> > #-------------------------
> >
> > #include <stdlib.h>
> > #include <stdio.h>
> >
> > int main(int argc, char **argv) {
> >  /* one wants a pointer to a raw ram - blank "piece of paper" */
> >  void* chunk;
> >
> >  / * make a particular bit pattern - our (old fashioned) "stamp"
> >
> >    http://cache.gawker.com/assets/images/gizmodo/2009/03/01.stamp.jpg
> >
> >  this "stamp" has a name "number"
> >
> >  */
> >  const int number = 1234567890;
> >
> >  /* integer "paper" (used later to hold the bit pattern above,
> >   as float
> >   */
> >  int i;
> >
> >  /* float "paper" (used later to hold the same bit pattern,
> >     but as integer
> >  */
> >  float f;
> >
> >  /* allocate untyped chunk of memory -
> >     create a "blank piece of paper" */
> >  chunk = calloc(sizeof(int), 1);
> >
> >  if( chunk == NULL ) {
> >    printf("cannot allocate\n");
> >    return 1;
> >  }
> >  else {
> >    /* initialise the blank memory (to particular bit pattern) using
> >    our "stamp" */
> >    /* means: initialise (i.e. set bits) in "chunk" as if it
> >       was integer, using "number" (which is an integer) */
> >    *(int *) chunk = number;
> >
> >    /* transfer the bit pattern (from "paper") as if it was float,
> >       to "paper" f (which is a float */
> >    f = *(float *) chunk;
> >
> >    /* transfer the same bit pattern (from "paper") as if it was
> >       integer, to "paper" i (which is an integer) */
> >    i = *(int *) chunk;
> >
> >    /* display 2 different interpretations of the same bit pattern */
> >    printf("%i\t%f\n", i, f);
> >  }
> >
> >  return 0;
> >
> > }
> >
> > /* eof */
> >
> > by the way, in the above, one could just write:
> >
> >    printf("%i\t%f\n", *(int *) chunk, *(float *) chunk);
> >
> > (kinda denser, but maybe clearer)
> >
> > It basicaly means: deallocate chunk as int pointer, deallocate chunk as
> > float pointer, print each as proper "type" (i.e. using particular
> > interpretation of bits in memory)...
> >
> >
> > Kind regards,
> >
> > Vladimir
> >
> > --
> >
> > Just because you have intelligence like a hammer,
> > you do not have to treat everyone else like a nail...
> >
> >    -- Principia Discordia (one of the versions)
> >
> _________________________________________________
>   For list-related administrative tasks:
>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme


Posted on the users mailing list.