By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
434,948 Members | 1,857 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,948 IT Pros & Developers. It's quick & easy.

Problem with pointer to function - what's wrong here?

P: n/a
I define and initialize an array of structures like the following,
(where the <verbiage within angle bracketsis just meant to be
explanatory):

int func1(<argument prototypes>);
int func2(<argument prototypes>);

struct mystruct {
<other stuff>;
int (*myfunc)();
} myrecords[] = {
{<other stuff value>, func1},
{<other stuff value>, NULL },
{<other stuff value>, func2}
};

int func1(<argument list>)
{
<blah-blah-blah1>
}

int func2(<argument list>)
{
<blah-blah-blah2>
}

I've always believed this was legal code, and have used something
similar a few times in the past, but now when (<argument list>) is:
(unsigned char x1, unsigned char x2, unsigned char x3,
int *y1, unsigned int *y2, int *y3)

I get the compiler message:
"warning: initialization from incompatible pointer type"

What am I doing wrong?

Thanks for your help.

Regards,
Charles Sullivan


Jan 31 '07 #1
Share this Question
Share on Google+
6 Replies


P: n/a
Charles Sullivan <cw******@triad.rr.comwrites:
int (*myfunc)();
[...]
I've always believed this was legal code, and have used something
similar a few times in the past, but now when (<argument list>) is:
(unsigned char x1, unsigned char x2, unsigned char x3,
int *y1, unsigned int *y2, int *y3)

I get the compiler message:
"warning: initialization from incompatible pointer type"
The problem is that there is no way to call a function with that
prototype, through a function pointer without a prototype,
without invoking undefined behavior. The reason is that, when
you invoke a function for which no prototype is available, the
integer promotions are performed on each argument (and arguments
of type float are converted to double). Thus, an "unsigned char"
argument will be converted to and passed as int (or unsigned int
on unusual implementations).

This rule for compatibility of function types is specified, in
C99, in section 6.7.5.3 paragraph 15:

For two function types to be compatible, both shall specify
compatible return types.125) Moreover, ... [if] one type
has a parameter type list and the other type is specified
by a function declarator that is not part of a function
definition and that contains an empty identifier list, the
parameter list shall not have an ellipsis terminator and
the type of each parameter shall be compatible with the
type that results from the application of the default
argument promotions.

It's a rather opaque paragraph, but I'm pretty sure that's what
it means.
--
int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv wxyz.\
\n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p[i]\
);}return 0;}
Jan 31 '07 #2

P: n/a
Charles Sullivan <cw******@triad.rr.comwrites:
I define and initialize an array of structures like the following,
(where the <verbiage within angle bracketsis just meant to be
explanatory):

int func1(<argument prototypes>);
int func2(<argument prototypes>);

struct mystruct {
<other stuff>;
int (*myfunc)();
} myrecords[] = {
{<other stuff value>, func1},
{<other stuff value>, NULL },
{<other stuff value>, func2}
};

int func1(<argument list>)
{
<blah-blah-blah1>
}

int func2(<argument list>)
{
<blah-blah-blah2>
}

I've always believed this was legal code, and have used something
similar a few times in the past, but now when (<argument list>) is:
(unsigned char x1, unsigned char x2, unsigned char x3,
int *y1, unsigned int *y2, int *y3)

I get the compiler message:
"warning: initialization from incompatible pointer type"

What am I doing wrong?
I don't believe you've given us enough information to answer that.
Show us some actual code that exhibits the problem. You don't have to
post your actual code (which is probably too big to post); you can
just replace <other stuffwith, say, "int x;", and
"<blah-blah-blah11>" with nothing.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jan 31 '07 #3

P: n/a
"Charles Sullivan" <cw******@triad.rr.comwrote in message
news:pa****************************@triad.rr.com.. .
>I define and initialize an array of structures like the following,
(where the <verbiage within angle bracketsis just meant to be
explanatory):

int func1(<argument prototypes>);
int func2(<argument prototypes>);

struct mystruct {
<other stuff>;
int (*myfunc)();
} myrecords[] = {
{<other stuff value>, func1},
{<other stuff value>, NULL },
{<other stuff value>, func2}
};

int func1(<argument list>)
{
<blah-blah-blah1>
}

int func2(<argument list>)
{
<blah-blah-blah2>
}

I've always believed this was legal code, and have used something
similar a few times in the past, but now when (<argument list>) is:
(unsigned char x1, unsigned char x2, unsigned char x3,
int *y1, unsigned int *y2, int *y3)

I get the compiler message:
"warning: initialization from incompatible pointer type"

What am I doing wrong?
The problem is probably here:
int (*myfunc)();
A modern compiler is going to demand that the input parameters (arguments)
to the function (as defined in the pointer type) be compatible with the
function prototype. I could make arguments based on full prototype linkage
and so on.

Just supply the argument list and I think you'll be OK.

--
David T. Ashley (dt*@e3ft.com)
http://www.e3ft.com (Consulting Home Page)
http://www.dtashley.com (Personal Home Page)
http://gpl.e3ft.com (GPL Publications and Projects)
Jan 31 '07 #4

P: n/a
Charles Sullivan wrote On 01/31/07 16:27,:
I define and initialize an array of structures like the following,
(where the <verbiage within angle bracketsis just meant to be
explanatory):

int func1(<argument prototypes>);
int func2(<argument prototypes>);

struct mystruct {
<other stuff>;
int (*myfunc)();
} myrecords[] = {
{<other stuff value>, func1},
{<other stuff value>, NULL },
{<other stuff value>, func2}
};

int func1(<argument list>)
{
<blah-blah-blah1>
}

int func2(<argument list>)
{
<blah-blah-blah2>
}

I've always believed this was legal code, and have used something
similar a few times in the past, but now when (<argument list>) is:
(unsigned char x1, unsigned char x2, unsigned char x3,
int *y1, unsigned int *y2, int *y3)

I get the compiler message:
"warning: initialization from incompatible pointer type"

What am I doing wrong?
Ben Pfaff has explained the error; here are suggestions
for a few fixes.

If all the (<argument prototype>) lists are identical, that's
the easiest case: just change the myfunc declaration inside the
struct to

int (*myfunc)(<argument prototypes>);

and all will be well. ("Identical" in argument count and types;
argument names, if any, don't matter.)

If the prototypes for func1(), func2(), etc. are not the
same, it's a bit harder. In the initializer list, you need to
convert each function pointer to the expected type:

{<other stuff value>, (int(*)())func1},
{<other stuff value>, (int(*)())NULL},
{<other stuff value>, (int(*)())func2},

You could improve the readability by introducing a typedef for
the function pointer casts; also, the cast of NULL isn't really
needed.

But that's not all! At the point where you actually use
the function pointer to call the pointed-to function, you need
to convert it back to the defined type of that called function.
This means you need some way of figuring out what that type is
supposed to be, perhaps with a type code in the <other stuff>.
Then you could write something like

switch (myrecords[i].type) {
case ONE_INT:
result = ((int(*)(int))myrecords[i].myfunc)(42);
break;
case TWO_DOUBLES:
result = ((int(*)(double,double))myrecords[i].myfunc)
(42.0, sqrt(42.0));
break;
...

Again, typedefs might improve the readability.

--
Er*********@sun.com
Jan 31 '07 #5

P: n/a
Keith Thompson <ks***@mib.orgwrites:
Charles Sullivan <cw******@triad.rr.comwrites:
I define and initialize an array of structures like the following,
(where the <verbiage within angle bracketsis just meant to be
explanatory):

int func1(<argument prototypes>);
int func2(<argument prototypes>);

struct mystruct {
<other stuff>;
int (*myfunc)();
} myrecords[] = {
{<other stuff value>, func1},
{<other stuff value>, NULL },
{<other stuff value>, func2}
};
[snip]
I get the compiler message:
"warning: initialization from incompatible pointer type"

What am I doing wrong?

I don't believe you've given us enough information to answer that.
Show us some actual code that exhibits the problem. You don't have to
post your actual code (which is probably too big to post); you can
just replace <other stuffwith, say, "int x;", and
"<blah-blah-blah11>" with nothing.
I think there was actually enough information to pinpoint the problem;
several other responders saw what I missed.

Posting actual code is still a good idea, though.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jan 31 '07 #6

P: n/a
On Wed, 31 Jan 2007 16:27:33 -0500, I wrote:
I define and initialize an array of structures like the following,
(where the <verbiage within angle bracketsis just meant to be
explanatory):

int func1(<argument prototypes>);
int func2(<argument prototypes>);

struct mystruct {
<other stuff>;
int (*myfunc)();
} myrecords[] = {
{<other stuff value>, func1},
{<other stuff value>, NULL },
{<other stuff value>, func2}
};

int func1(<argument list>)
{
<blah-blah-blah1>
}

int func2(<argument list>)
{
<blah-blah-blah2>
}

I've always believed this was legal code, and have used something
similar a few times in the past, but now when (<argument list>) is:
(unsigned char x1, unsigned char x2, unsigned char x3,
int *y1, unsigned int *y2, int *y3)

I get the compiler message:
"warning: initialization from incompatible pointer type"

What am I doing wrong?
Many thanks Ben, Keith, David and Eric!

Ben nailed it with his explanation of promoting (which also
clarifies some other unrelated cryptic compiler messages I've
gotten). Thanks Ben.

Keith: Yes, It's good to post actual code, but it can be complex
and confusing unless boiled down to the essentials. Of course I
don't always succeed in identifying the essentials. :-)

David and Eric: Thanks for the practical solutions which I will
keep in mind. In this _particular_ case the neatest approach
was to rewrite the functions to make all the arguments int or
int * and do my own conversion back and forth when I call them.

Thanks again guys - the expertise in this newsgroup has once more
restored my sanity!

Regards,
Charles Sullivan



Feb 1 '07 #7

This discussion thread is closed

Replies have been disabled for this discussion.