C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Please explain this code

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C Language (Moderated)
View previous topic :: View next topic  
Author Message
Guest






PostPosted: Mon Apr 16, 2007 8:18 pm    Post subject: Please explain this code Reply with quote



Exec_Mem (unsigned long address)
{
void (* foo) () = void (*) () address;
foo ();
}

I understand that foo is a function pointer to type void, but can
someone please explain the right hand side of the equation? Is this a
cast of some type or what?

Thanks for your help,
Fred.
--
comp.lang.c.moderated - moderation address: clcm (AT) plethora (DOT) net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Back to top
Martin Ambuhl
Guest





PostPosted: Thu Apr 19, 2007 7:13 pm    Post subject: Re: Please explain this code Reply with quote



fred.zakity (AT) gmail (DOT) com wrote:
Quote:
Exec_Mem (unsigned long address)
{
void (* foo) () = void (*) () address;
foo ();
}

I understand that foo is a function pointer to type void, but can
someone please explain the right hand side of the equation? Is this a
cast of some type or what?

It's an assignment, not an equation.
Apparently the writer of this code wrote it for an implementation in
which unsigned longs and addresses can safely be interconverted. This
is by no means guaranteed. However, he has a compiler that knows that
this is a bad idea, so he uses the cast to silence the compiler
diagnostics. And that cast is missing a level of parentheses.

Consider these programs:
1) Corresponding roughly to the above case
void nothing(void)
{
}

void Exec_Mem(unsigned long address)
{
void (*foo) () = (void (*)()) address;
foo();
}

int main(void)
{
unsigned long crap = (unsigned long) nothing;
Exec_Mem(crap);
return 0;
}

This is an unportable program, but the programmer, having suppressed
diagnostics with casts probably is blissful and proud.

2) But we know that casts are to be avoided when possible, so let's
remove them. The diagnostics are from gcc.

void nothing(void)
{
}

void Exec_Mem(unsigned long address)
{
void (*foo) () = address; /* line 7 */
foo();
}

int main(void)
{
unsigned long crap = nothing; /* line 13 */
Exec_Mem(crap);
return 0;
}


a.c: In function 'Exec_Mem':
a.c:7: warning: initialization makes pointer from integer without a cast
a.c: In function 'main':
a.c:13: warning: initialization makes integer from pointer without a cast

This is the situation the programmer was seeking to avoid. Instead of
fixing the interconversion of integers and pointers, he used casts to
hide the problem.

3) Here's how he could have fixed it:
void nothing(void)
{
}

void Exec_Mem(void address())
{
void (*foo) () = address;
foo();
}

int main(void)
{
void (*crap) () = nothing;
Exec_Mem(crap);
return 0;
}
--
comp.lang.c.moderated - moderation address: clcm (AT) plethora (DOT) net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Back to top
Hans-Bernhard Bröker
Guest





PostPosted: Thu Apr 19, 2007 7:14 pm    Post subject: Re: Please explain this code Reply with quote



fred.zakity (AT) gmail (DOT) com wrote:
Quote:
Exec_Mem (unsigned long address)
{
void (* foo) () = void (*) () address;
foo ();
}

I understand that foo is a function pointer to type void, but can
someone please explain the right hand side of the equation? Is this a
cast of some type or what?

It's someone's broken attempt at doing such a cast. For this to be an
actual cast, there would have to be one more pair of parentheses.

That said, be advised that if you don't understand this code, it's
probably not safe for being used by you. You're a user in a "no
user-serviceable parts behind this cover" area.
--
comp.lang.c.moderated - moderation address: clcm (AT) plethora (DOT) net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Back to top
Douglas A. Gwyn
Guest





PostPosted: Thu Apr 19, 2007 7:14 pm    Post subject: Re: Please explain this code Reply with quote

fred.zakity (AT) gmail (DOT) com wrote:
Quote:
void (* foo) () = void (*) () address;
... Is this a cast of some type or what?

It's supposed to be, but it's missing the outer parentheses:
void (* foo) () = (void (*) ()) address;
--
comp.lang.c.moderated - moderation address: clcm (AT) plethora (DOT) net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Back to top
Jack Klein
Guest





PostPosted: Thu Apr 19, 2007 7:15 pm    Post subject: Re: Please explain this code Reply with quote

On 16 Apr 2007 15:18:44 GMT, fred.zakity (AT) gmail (DOT) com wrote in
comp.lang.c.moderated:

Quote:
Exec_Mem (unsigned long address)
{
void (* foo) () = void (*) () address;
foo ();
}

I understand that foo is a function pointer to type void, but can
someone please explain the right hand side of the equation? Is this a
cast of some type or what?

As written it has at least three problems:

1. It uses implicit int to define "Exec_Mem" as a function returning
an int. This is invalid under the current version of the C standard.

2. "Exec_Mem" is defined as returning an int, but does not return
anything. This causes undefined behavior if the caller tries to use
the return value.

3. The line "void (* foo) () = void (*) () address;" is not some kind
of cast it a syntax error.

If you remove the syntax error on that line by rewriting it as:

void (* foo) () = (void (*) ()) address;

....then it is an attempt to cast an unsigned long to a pointer to a
function returning nothing and accepting a fixed, but unspecified,
number of arguments.

Once you fix this, the code has two more problems:

4. The result of converting an unsigned long to a pointer type is
implementation-defined, might not be properly aligned, might not point
to what you want it to point to, and might be a trap representation.

5. Trying to actually call a function through the resulting pointer
is totally undefined.

It is an example of a bad idea, coded poorly.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
--
comp.lang.c.moderated - moderation address: clcm (AT) plethora (DOT) net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Back to top
Kevin Ashley
Guest





PostPosted: Thu Apr 19, 2007 7:15 pm    Post subject: Re: Please explain this code Reply with quote

fred.zakity (AT) gmail (DOT) com wrote:
Quote:
Exec_Mem (unsigned long address)
{
void (* foo) () = void (*) () address;
foo ();
}

I understand that foo is a function pointer to type void, but can
someone please explain the right hand side of the equation? Is this a
cast of some type or what?


Foo is a pointer to a function which takes no arguments and returns
no value, as you've worked out. And yes, the stuff on the RHS is
probably intended to be a cast to achieve the same effect. (But
I'm guessing here.) Some brackets would help it to achieve that;
as it stands, I don't think it's syntactically valid.
--
comp.lang.c.moderated - moderation address: clcm (AT) plethora (DOT) net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Back to top
Guest






PostPosted: Thu Apr 19, 2007 7:15 pm    Post subject: Re: Please explain this code Reply with quote

On Apr 16, 11:18 am, fred.zak...@gmail.com wrote:
Quote:
I understand that foo is a function pointer to type void, but can
someone please explain the right hand side of the equation? Is this a
cast of some type or what?

'address' is being casted to a function pointer of the appropriate
type. The function allows you to pass in an actual address by value,
and then tries to execute code beginning there.
------------------------------
#include <stdio.h>

void Exec_Mem(unsigned long address) {
void (* foo) () = (void (*) ()) address; /* Added parens to get
gcc to recognize the cast. */
foo();
}

void blah() {
printf("Hello world.\n");
}

int main(void) {
Exec_Mem((unsigned long)blah);
return 0;
}
-------------------------
On a personal note, the fact that this function exists makes my skin
crawl. Wink
--
comp.lang.c.moderated - moderation address: clcm (AT) plethora (DOT) net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Back to top
Keith Derrick
Guest





PostPosted: Mon May 07, 2007 9:12 am    Post subject: Re: Please explain this code Reply with quote

I hate to say this, but I can see a valid use for something like this
Exec_Mem function 8( Obviously, it needs all the casting corrections which
other have pointed out. But everyone also seems to be assuming Exec_Mem will
be used to execute code in the image, where a function of the appropriate
type is available, and therefore its address will be cast to an unsigned
long and then passed to Exec_Mem.

Instead consider the following example, perhaps from a ROM'd embedded system
with patches stored in EEPROM. For the sake of argument, assume that the
processor supports Position-Independent-code (the 6809 could certainly
manage it). I'm also not going to bother with any error checking etc, to
keep the example clean.

typedef void (* vfPtr)();
extern int getpatchSize(const char * patchName); // Returns 0 if patch not
found
extern void LoadPatch(const char * patchName, int patchSize, vfPtr Buffer );
// Loads patch into *buffer

void ExecutePatch( const char * const patchName )
{
int patchSize = GetPatchSize(patchName);
vfPtr patchCode;

if (patchSize)
{
patchCode = (vfPtr) malloc (patchSize);
LoadPatch(patchName, patchSize, patchCode);
patchCode();
free(patchCode);
}
}

Keith

<fred.zakity (AT) gmail (DOT) com> wrote in message
news:clcm-20070416-0046 (AT) plethora (DOT) net...
Quote:
Exec_Mem (unsigned long address)
{
void (* foo) () = void (*) () address;
foo ();
}

--

comp.lang.c.moderated - moderation address: clcm (AT) plethora (DOT) net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.