- Casting function pointers into data and back - 1 Update
- Casting function pointers into data and back - 7 Updates
- NEWBIE question: Is this a bug in my compiler? - 1 Update
- escape sequence '\(' - 1 Update
ram@zedat.fu-berlin.de (Stefan Ram): Jun 23 10:24PM Ghost <no@spam.net> writes: Is it possible >to cast a function pointer into some primitive type and >back in a safe and portable way? The following program shows how one can convert functions to ints and vice versa. In the function »main«, the function »integerof« is called (via »printnumeralof«) to convert each of the functions »iota« and »zeta« into integers. Then the function »functionof« is called (via »executefunctionof«) to convert each of the numbers »0« and »1« into functions. The functions obtained this way than even can be called. So, the output of the program is: 0 1 Lima Zulu . /* < filename = [intcall.c] encoding = [ANSI_X3.4-1968] notation = [ISO/IEC 9899:1999 (E)] author = [Stefan Ram] > */ #include <stdio.h> /* puts */ #include <string.h> /* strcmp */ typedef void( *function_t )( void ); #define F(r,n,b) r n b #define FUNCTIONS \ F( void, iota, ( void ){ puts( "Lima" ); } )\ F( void, zeta, ( void ){ puts( "Zulu" ); } )\ /**/ FUNCTIONS #undef F #define F(r,n,b) n, void( * const function[] )() ={ FUNCTIONS }; #undef F int const top = sizeof function / sizeof 0[ function ]; /** convert an int value into a function */ function_t functionof( int const i ){ return i[ function ]; } /** convert a function into an int value */ int integerof( function_t const f ) { for( int i = 0; i < top; ++i ) if( f == i[ function ])return i; } void printnumeralof( function_t const f ) { printf( "%d\n", integerof( f )); } void executefunctionof( int const i ) { functionof( i )(); } int main( void ) { printnumeralof( iota ); printnumeralof( zeta ); executefunctionof( 0 ); executefunctionof( 1 ); } |
Ghost <no@spam.net>: Jun 23 02:05PM -0300 HI there, I find myself in a situation where I can only pass around structs with no pointer members. However, I would like to include information about function pointers. Is it possible to cast a function pointer into some primitive type and back in a safe and portable way? If I use reinterpret_cast, is the success of the operation only a matter of the new type being large enough? If it is of any help, I'm trying to use the standardized Fortran mechanism to mix Fortran and C, but I can only have Fortran /derived types/ be mapped into C structs if no pointer members are involved. Also, Fortran doesn't define /interoperability/ between Fortran and C++, so I also mix C++ and C using extern "C". Another limitation is that Fortran doesn't have unsigned types. Any help appreciated. Thanks. |
Victor Bazarov <v.bazarov@comcast.invalid>: Jun 23 01:38PM -0400 On 6/23/2016 1:05 PM, Ghost wrote: > is the success of the operation only a matter of the new > type being large enough? > [..] Yes, all correct, if your implementation provides an integral type large enough to accommodate a pointer (to function, to object), you can use 'reinterpret_cast' to do the casting forth and back between a pointer and that integral type. There is no standard type, it's all implementation-specific ([expr.reinterpret.cast]/4 and /5). V -- I do not respond to top-posted replies, please don't ask |
Ben Bacarisse <ben.usenet@bsb.me.uk>: Jun 23 07:53PM +0100 > include information about function pointers. Is it possible > to cast a function pointer into some primitive type and > back in a safe and portable way? I don't think you can do it with a cast in a 100% portable way. You can include cstdint and test for UINTPTR_MAX which will tell you if there is a type uintptr_t type that can hold a pointer value (or, alternatively, INTPTR_MAX for the signed version) but even that is only guaranteed to work for object pointers. The only portable method would be to copy the representation: typedef void (*function_ptr)(); unsigned char fptr_rep[sizeof (function_ptr)]; ... function_ptr fp = ...; memcpy(fptr_rep, &fp, sizeof fp); but that, of course, is clumsy. <snip> -- Ben. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 23 09:13PM +0200 On 23.06.2016 20:53, Ben Bacarisse wrote: > a type uintptr_t type that can hold a pointer value (or, alternatively, > INTPTR_MAX for the signed version) but even that is only guaranteed to > work for object pointers. Since C++11 an implementation can support casting function pointer to void* and back. Essentially because the Posix API requires that. And then uintptr_t is necessarily large enough. C++11 §5.2.10/8: «Converting a function pointer to an object pointer type or vice versa is conditionally-supported. The meaning of such a conversion is implementation-defined, except that if an implementation supports conversions in both directions, converting a prvalue of one type to the other type and back, possibly with different cv-qualification, shall yield the original pointer value.» > function_ptr fp = ...; > memcpy(fptr_rep, &fp, sizeof fp); > but that, of course, is clumsy. Yep. But I'd go for the portable-enough uintptr_t. ;-) Cheers!, - Alf |
legalize+jeeves@mail.xmission.com (Richard): Jun 23 07:32PM [Please do not mail me a copy of your followup] Ghost <no@spam.net> spake the secret code >[...] Is it possible >to cast a function pointer into some primitive type and >back in a safe and portable way? Not really <http://stackoverflow.com/questions/12358843/why-are-function-pointers-and-data-pointers-incompatible-in-c-c> -- "The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline> The Computer Graphics Museum <http://computergraphicsmuseum.org> The Terminals Wiki <http://terminals.classiccmp.org> Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com> |
Ben Bacarisse <ben.usenet@bsb.me.uk>: Jun 23 09:13PM +0100 > Since C++11 an implementation can support casting function pointer to > void* and back. Essentially because the Posix API requires that. And > then uintptr_t is necessarily large enough. Yes, I wasn't very clear at all. I should have pointed out that converting to uintptr_t only works for void * (I think C++ defers to C on this matter) so you can't ever convert a function pointer directly. (in the standard sense that is -- it is, of course, very likely to work in practice). Thus two things are needed: the uintptr_t type and the (two-way) conversion between function pointers and object pointers. > C++11 §5.2.10/8: Thanks for the quote. I didn't know this happened so late! <snip> >> The only portable method would be to copy the representation: <snip> > But I'd go for the portable-enough uintptr_t. ;-) Sure, me too, but the OP's request was so odd (why no function pointers in the structures?) that they may be looking at some very odd hardware that really can't do it any other way. -- Ben. |
scott@slp53.sl.home (Scott Lurndal): Jun 23 08:19PM >Sure, me too, but the OP's request was so odd (why no function pointers >in the structures?) that they may be looking at some very odd hardware >that really can't do it any other way. He's sharing the structure between fortran and C, and fortran creates the C-structure definition used based on the COMMON data being shared. |
kfrank29.c@gmail.com: Jun 22 06:31PM -0700 Hi Mehrdad! On Wednesday, June 22, 2016 at 11:07:15 AM UTC-4, mehrdad ghassempoory wrote: > however, if I use clang++ version 3.5, I get what I expected: > 0 2 > Is this a bug in gnu c++ This is not a bug in g++. Both g++ and clang++ are right, because (see below) your program has unspecified behavior, which means that the standard gives the compiler a choice, and g++ and clang++ are (apparently) making different choices. > or maybe I am confused about the way << > operator works? Because the library uses "operator overloading" to let "<<" work with streams, "<<", in your case, is just a function that takes two arguments. The order of evaluation of arguments to functions is unspecified by the standard, so either the first or the second argument may be evaluated first. (This is not changed by the fact that your function call is written as an infix operator.) > int x; > x=0; > cout << func(x) << " " << x << endl; To see what is happening, let's rewrite this with explicit function-call notation: operator<< ( operator<< ( // this is the relevant function call operator<< ( operator<< ( cout, func(x) ), " ", ), x ), endl ); The second "operator<<" (noted by the comment) is called with two arguments. The first is the result of evaluating the third "operator<<", and the second is x, itself. If you evaluate the first argument first (as, apparently, does clang++) you drill down and call func(x) which sets x to 2 (and returns zero). You then evaluate x, which is now 2. So you print out "0 2". If you evaluate the second argument first (as, apparently, does g++), you evaluate x, which is 0, and then call func(x), which sets x to 2 -- but this does not change the value of 0 from the earlier evaluation of x -- and returns 0. So you print of "0 0". > ... To recap: Both results, "0 2" and "0 0" are perfectly legal, because they depend upon in which order the two arguments of operator<< are evaluated, and this is explicitly stated to be unspecified in the standard, with the choice left up to the compiler. Good luck. K. Frank |
Kalle Olavi Niemitalo <kon@iki.fi>: Jun 23 03:09AM +0300 > The question really should be "why does g++ accept this non-standard > escape sequence?". Which, of course, only the authors, documentation > and/or source code comments of g++ can tell you. The C source code of GNU Emacs often uses \( to escape the opening parenthesis when it occurs at the beginning of a line in a multiline string literal. AFAIK, this helps Emacs understand that the parenthesis does not mark the start of a function, when the source code of Emacs is being edited with Emacs itself. Because GCC and Emacs are flagship GNU packages, it seems reasonable for GCC not to warn about Emacs conventions by default. https://www.gnu.org/prep/standards/html_node/Formatting.html also advises against starting a line with an opening parenthesis. It does not mention the backslashes though. |
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment