On Wed, Mar 07, 2012 at 11:10:21AM -0300, Isaac Marino Bavaresco wrote: > Em 7/3/2012 10:57, Bob Ammerman escreveu: > >> Sometimes I love how C can be obscure and powerful, when you can write > >> something like this: > >> > >> ( (void (*)(void))0x4ff0 )(); > >> > >> > >> ... and it works. > >> > >> > >> Isaac > > Completely non-standard, but it works on many (most?) platforms. > > > > -- Bob Ammerman > > RAm Systems >=20 >=20 > Completely standard and should work in every platform. The only > non-standard thing is the fixed address, that will be platform-dependent. > There are (not much) clearer ways to write it though: >=20 > typedef void (*functionpointer_t)( void ); >=20 > #define myfunc() ( (functionpointer_t)0x4ff0 )() >=20 > ... > myfunc(); > ... This is much clearer. In the first one, the lack of a type/variable name in the cast threw off my understanding for a moment. I realized finally that it's the same as the second one with the name missing. The second way is always how I write it. Once one realizes that a function call is an operator that takes a pointer to a function, and that the precedence of the function call is higher than the pointer definition it becomes clearer. I always explain it as the same reason that: 5+3*2 is not 16. and that if we wanted 16, then we'd have to write: (5+3)*2 to change the precedence. So by the same token: void *f1(void); has two "operators": function call and pointer. Since function call has the higher precendence, and there are no grouping parens (as the parens there are the function call), then this reads: f1 is a function that is called and returns a void pointer. By changing the precedence using grouping parens you get this: void (*f2)(void); Now just like (5+3)*2 this is completely different than 5+3*2. It reads: f2 is a pointer to a function that takes no parameters and returns nothing. Key point is that it's a pointer first and foremost now. And just like any pointer it can be assigned an address. Simplest way: f2 =3D (void *) 0x4ff0; as a void pointer can be put into any pointer type without complaint via autocasting. So f2 is now a pointer with 0x4ff0 and is defined as a pointer to a function. Since the function call operator takes a pointer to a function and calls the function then this is now perfectly valid: f2() Which calls the function in the address that f2 currently contains. So the original line does all of this in a single step doing the cast and the call on the same line. Extra parens are put in to ensure that the cast is done before the function call and remember that a cast needs parens around the type. The type is generated by using the original variable definition void (*f2)(void) and removing the variable name. And so one gets: ((void (*)(void)) 0x4ff0) () Which I believe is the original statement. To highlight I'll use braces for the cast parens and brackets for the grouping parens: [ { void (*)(void) } 0x4ff0 ] () See how clear it can be? ;-) BAJ >=20 >=20 > Isaac >=20 > --=20 > http://www.piclist.com PIC/SX FAQ & list archive > View/change your membership options at > http://mailman.mit.edu/mailman/listinfo/piclist --=20 Byron A. Jeff Department Chair: IT/CS/CNET College of Information and Mathematical Sciences Clayton State University http://cims.clayton.edu/bjeff --=20 http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist .