|
|
 |
 |
 |
 |
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).
jois.de.vi @gmail.com wrote: > 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?
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
jois.de.vi @gmail.com wrote: > 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).
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:
> jois.de.vi @gmail.com wrote: > > 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? > 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
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...
>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).
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
<jacek.dziedzic.n.o.s.p. @gmail.com> wrote: > jois.de.vi @gmail.com wrote: > > 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). > 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 :>). 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
|
 |
 |
 |
 |
|