Re: working with addresses

From: Arthur J. O'Dwyer (ajo_at_nospam.andrew.cmu.edu)
Date: 01/11/04


Date: Sun, 11 Jan 2004 13:18:07 -0500 (EST)


On Sun, 11 Jan 2004, pcrAKAJumbo wrote:
>
> "Richard Heathfield" <dontmail@address.co.uk.invalid> wrote...
> > thides wrote:
> > > I guess you can't
> > > make the digits of a hexadecimal number into a workable string...
> >
> > Well, actually you can do this fairly easily in C, even for object
> > pointers (i.e. this technique is not guaranteed to be portable to
> > function pointers).
> >
> > Given that we can convert any object pointer into a void *, and back
> > again, without loss of information, we conclude that a void * is big
> > enough to hold all the information bits of any object pointer. We
> > therefore know that we need only provide an array of unsigned char
> > sizeof(void *) bytes long to get a object representation. From this
> > object representation it is a relatively trivial matter to get a
> > displayable string.
>
> Is it not true that sizeof(anypointer) will yield the same result?

  That's right; it's not true that sizeof(anypointer) will yield
the same result. Besides the obvious difference between pointers
to data and pointers to functions, it could be that a pointer to
an aligned 1000K-sized object just doesn't require as many bits
of precision as a pointer to char. Some compilers *will* make
the obvious optimization, if the system supports it.

> > First, copy the pointer information into the array of unsigned char:
> >
> > unsigned char p[sizeof(void *)] = {0};
> > memcpy(p, &wnn_Pointer, sizeof p);

  Whoops! (Richard may have corrected himself already; I don't
know; but it should be

    memcpy(p, &wnn_Pointer, sizeof wnn_Pointer);

...and if I were doing it, I'd take the extra couple lines to
"right-justify" the pointer value so that any extra zero bytes
showed up on the left instead of on the right. In practice,
on the OP's computer, there will be no appreciable difference.)

> > Then build your nybbles:
> >
> > for(thisbit = 0; thisbit < bits; thisbit += 4) /* 4 bits per nybble */
> > {
> > nybble = WNN_TEST_BIT(p, thisbit + 3) << 3;
> > nybble |= WNN_TEST_BIT(p, thisbit + 2) << 2;
> > nybble |= WNN_TEST_BIT(p, thisbit + 1) << 1;
> > nybble |= WNN_TEST_BIT(p, thisbit + 0);
> > wnn_Destination[WNN_POINTER_STRING_SIZE - thisbit / 4 - 2] =
> > hexit[nybble];
> > }
>
> Additionally:
> On a 32bit system any pointer will be 4 bytes

  Possibly. But not only am I not sure this is a justified
assumption (unless I'm missing a definition of "32-bit system"
somewhere), the C language doesn't say anything about how many
bits your system should have.

> so there are probably numerous
> ways to break this value into byte size pieces or Nibbles.
> Therefore if you have:
>
> int myInt=1;
> void* ptr = &myInt;
> char str[9];
> itoa( (int)ptr, str, 16 );
> printf(str);

  You probably meant
  sprintf(str, "%p", ptr);
  printf("%s\n", str);

(and you probably also meant to declare 'str' with a few more
chars of space, just for safety's sake).

> This would yield the same results if you were to use any type of pointer ie:
>
> int myInt=1;
> char* ptr = (char*)&myInt;
> char str[9];

  sprintf(str, "%p", (void *)ptr);
  printf("%s\n", str);

> int myInt=1;
> long* ptr = (long*)&myInt;

  This isn't even guaranteed to produce a meaningful result,
you know. Even on plain old PCs, 'long' and 'int' could
have different alignment restrictions.

  And no, this last one is *not* guaranteed to yield the
same result as the (void*) and (char*) examples. Because
the conversion (int*) -> (long*) -> (int*) is not guaranteed
to be lossless. Because even on plain old PCs, 'long' and
'int'... et cetera.

> Using the itoa function however put each hexadecimal digit into a Byte thus
> requiring an 8 byte char array.
> On my system function pointers also work

  Terrific. I'm happy for you.

> Can you please explain why you specifically state that this is not
> guaranteed for function pointers?

  Because it specifically is not guaranteed for function pointers.
The conversion (void(*)()) -> (void*) -> (void(*)()) is not
guaranteed to be lossless.

  Trivia for the experts: But the following assignment is legal
without a cast, and perfectly well-defined, am I correct?

  void (*foo)();

  foo = (void*) 0; /* null pointer constant, right? */

-Arthur



Relevant Pages

  • Re: How are C++ objects laid out in memory ?
    ... If a C++ class or struct contains no virtual methods, ... There are no function pointers. ... >pointers which I can locate and then invoke the function pointers? ...
    (comp.lang.asm.x86)
  • Re: Subtracting strings
    ... This is allowed as long as the pointers involved point to ... into the string pointed to by 'pathname') and then return the ... const char *fname; ... memory pointed to what 'pathname' points to, 'str' now points to ...
    (comp.lang.c)
  • How are C++ objects laid out in memory ?
    ... Optimizing Compiler v. 13.10.3052". ... But the function pointers declared in above MsgStruct structure have to ... pointers which I can locate and then invoke the function pointers? ...
    (comp.lang.asm.x86)
  • Re: virtual functions vs speed
    ... > I have been thinking about using function pointers but that seems as ... Virtual functions work via pointers (just to cover my bases here: ... ever played the game Mortal Kombat? ... there's a character in it called Shang Tsung who can morph into every other ...
    (comp.lang.cpp)
  • Re: Dynamic linking with symbols
    ... Thus I need to either pass all the singeltons pointers or pass function pointers to functions hooking the callbacks into the singeltons. ... plugin writer to use a c style interface. ...
    (microsoft.public.vc.language)