Home     |     .Net Programming    |     cSharp Home    |     Sql Server Home    |     Javascript / Client Side Development     |     Ajax Programming

Ruby on Rails Development     |     Perl Programming     |     C Programming Language     |     C++ Programming     |     IT Jobs

Python Programming Language     |     Laptop Suggestions?    |     TCL Scripting     |     Fortran Programming     |     Scheme Programming Language


 
 
Cervo Technologies
The Right Source to Outsource

MS Dynamics CRM 3.0

C++ Programming

Casting from pointer types to non-pointer types


I am interfacing with a third party API (written in C, if that
matters) that has an "event handler" function with the following
definition:

void event_handler(int event_code, unsigned long user_data);

The function takes an event code along with the user data but does not
act on or change the user data.
In my application, I want to pass a pointer as the user data.  This
pointer is to an array allocated with new, say, as follows:

char *array = new char[100];

and passed to the event handler as follows:

event_handler(1, reinterpret_cast<unsigned long>(array));

My question is if it's safe to cast this to an unsigned long type if I
want to reuse it later? Specifically will doing something like this
cause me any trouble?

void some_function(unsigned long pointer)
{
    char *array = reinterpret_cast<char*>(pointer);
    /* do stuff with array */
    delete [] array;

}

On my machine both sizeof(char*) and sizeof(unsigned long) is 8 so
while this is a pretty ugly solution, at first glance it would seem
safe (at least from overflow).

It is safe and well-defined _if_ 'unsigned long' has the same size as
the pointer to which you're casting it.

> void some_function(unsigned long pointer)
> {
>    char *array = reinterpret_cast<char*>(pointer);
>    /* do stuff with array */
>    delete [] array;
> }

> On my machine both sizeof(char*) and sizeof(unsigned long) is 8 so
> while this is a pretty ugly solution, at first glance it would seem
> safe (at least from overflow).

It is.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

   I think it would be "generally unsafe", but if your unsigned longs
really are 8 byte, then it will work. Still, an assert() that
sizeof(unsigned long)==sizeof(char*) somewhere in your code
won't hurt (and it will help others in 20 years' time track
the bug as they port your code to machines using "__further",
16-byte pointers :>).

HTH,
- J.

It should be safe. I believe in all current compiler, long and pointer
have same size. Please google "LP64" for more information.
Please quote some context. See my signature.

g@yahoo.com wrote:
> It should be safe. I believe in all current compiler, long and pointer
> have same size. Please google "LP64" for more information.

Not safe.
On a 64bit Windows system, a pointer has 64bit, but long has 32bit like an int.

--
Thomas
http://www.netmeister.org/news/learn2quote.html

g@yahoo.com wrote:
> It should be safe. I believe in all current compiler, long and pointer
> have same size. Please google "LP64" for more information.

Win64 - BAM! - Pointers are 64 bit and longs are 32 bit.
On Jun 6, 12:13 pm, "Victor Bazarov" <v.Abaza@comAcast.net> wrote:

If the sizes differ, will the cast fail with a "loses precision"
error, such as attempting to cast from a pointer to say, an int?

char *array = new char[100];
int ptr_val = reinterpret_cast<int>(array);

on gcc:
error: cast from 'char*' to 'int' loses precision

not sure if this is true with all compilers ...

jois.de.vi@gmail.com wrote:
> [..]
> If the sizes differ, will the cast fail with a "loses precision"
> error, such as attempting to cast from a pointer to say, an int?

The Standard doesn't say what error message will be displayed.  It
is up to the implementation.

> char *array = new char[100];
> int ptr_val = reinterpret_cast<int>(array);

> on gcc:
> error: cast from 'char*' to 'int' loses precision

> not sure if this is true with all compilers ...

It is not.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

<jois.de.vi@gmail.com> wrote in message

news:1181152296.056325.121820@o11g2000prd.googlegroups.com...

Are you sure you are doing what you think you are doing?

array is a char pointer.  It contains the address of the 100 characters that
new allocated.  Your reinterpret_cast<unsigned long>( array ) is
reinterpreting this *pointer* to an integer.  I suspect you actually wanted
to use the buffer itself to hold the integer.  Am I correct?

This program for one run on my system outputs:
4
3288656

Which is it you wanted to use?  Notes follow the code.

#include <iostream>

void event_handler(int event_code, unsigned long user_data)
{
    std::cout << user_data << "\n";

}

int main()
{
    char *array = new char[100];

    array[0] = 4;
    array[1] = 0;
    array[2] = 0;
    array[3] = 0;
    array[4] = 0;
    array[5] = 0;
    array[6] = 0;
    array[7] = 0;

    event_handler(1, *reinterpret_cast<unsigned long*>( array ));
    event_handler(1, reinterpret_cast<unsigned long>( array ));

    return 0;

}

This can be dangerous on some systems (treating the contents of some other
type as an integer) becasue of byte alignment.  On some systems if an
integer is not correctly byte aligned the program can run slower,
malfunction or crash.  Generally a integral type needs to be aligned on it's
size.  A 4 byte integer on a byte evenly divisible by 4.  An 8 byte integer
on a byte evenly divisible by 8, etc...  So in that case, if you need to use
the buffer itself as the integer, it may not be safe depending on your
platform.

Notice how I'm passing the *contents* of the buffer as an unsigned long.  I
cast the char pointer to an unsigned long pointer, then derefence it (asking
for it's contents).

On Jun 6, 10:28 pm, "Victor Bazarov" <v.Abaza@comAcast.net> wrote:

> jois.de.vi@gmail.com wrote:
> > [..]
> > If the sizes differ, will the cast fail with a "loses precision"
> > error, such as attempting to cast from a pointer to say, an int?
> The Standard doesn't say what error message will be displayed.  It
> is up to the implementation.
> > char *array = new char[100];
> > int ptr_val = reinterpret_cast<int>(array);
> > on gcc:
> > error: cast from 'char*' to 'int' loses precision
> > not sure if this is true with all compilers ...
> It is not.

Are you sure.  According to the standard, "A pointer can be
explicitly converted to any integral type large enough to hold
it."  (From the section on reinterpret_cast.)  Converting a
pointer to an integral type which is not large enough to hold it
cannot be done using reinterpret_cast.  A compiler is required
to emit a diagnostic.

According to the C++ standard, the same thing holds for a C
style cast.  In C, however, it is undefined behavior, and
C compilers historically have supported it, so that I expect a
lot of C++ compilers will accept it unless you request strict
conformance.  Both Sun CC and g++ give an error regardless of
the type of cast, in default mode.  Using a C-style cast in C
provokes a warning from gcc, and nothing from Sun cc, however.
This is a point where the two languages differ.

The other direction is fine, however, and there is no problem
using reinterpret_cast to convert a char to a pointer.

In the case in question, the poster needed a round trip
conversion pointer to integral type back to pointer.  This
obviously can only work if the integral type is large enough.
Most of the time, however, it is the reverse that is needed; the
de facto standard "user data" type is void*, and if all you need
is a char... char->void*->char is forbidden by the standard, you
have to use char->void*->intptr_t->char.  (And if the system
doesn't have an intptr_t, then you're out of luck.)

--
James Kanze (GABI Software)             email:james.ka@gmail.com
Conseils en informatique oriente objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place Smard, 78210 St.-Cyr-l'cole, France, +33 (0)1 30 23 00 34

On Jun 6, 8:24 pm, Jacek Dziedzic

If the integral type isn't long enough, the code shouldn't
compile, at least according to the C++ standard (and the
compilers I have at hand).

--
James Kanze (GABI Software)             email:james.ka@gmail.com
Conseils en informatique oriente objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place Smard, 78210 St.-Cyr-l'cole, France, +33 (0)1 30 23 00 34

On Jun 6, 8:39 pm, g@yahoo.com wrote:

> It should be safe. I believe in all current compiler, long and pointer
> have same size. Please google "LP64" for more information.

It's certainly not required, and in the past, I've used
compilers with 6 byte pointers and 4 byte longs.  I've also
heard rumors that some 64 bit Windows compilers have 32 bit
longs---it seems stupid, but you never know.  I would certainly
never assume that an unsigned long is big enough to hold a
pointer on all systems, or even that there is an integral type
large enough to hold a pointer.  (If I'm not mistaken, at the
hardware level, pointers can be 80 bits on a 64 bit Intel or
AMD, even though the largest integral type is only 64 bits.)

--
James Kanze (GABI Software)             email:james.ka@gmail.com
Conseils en informatique oriente objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place Smard, 78210 St.-Cyr-l'cole, France, +33 (0)1 30 23 00 34

Add to del.icio.us | Digg this | Stumble it | Powered by Megasolutions Inc