I have the following code
#include <stdio.h>
void a(void) {
printf("a called.\n");
}
int b(void) {
printf("b called.\n");
return 0x1;
}
int main(void) {
void (*p)(void);
p = a;
p();
p = b;
p();
return 0;
}
However, it does issue a warning that I am trying to assign a function
of wrong type. Is there any portable way to say to the compiler "shut
up, I know what I am doing?"
And what is the most common way of declaring and using function
pointers, the above or this?
p = &a;
(*p)();
--
one's freedom stops where others' begin
Giannis Papadopoulos http://dop.users.uth.gr/
University of Thessaly
Computer & Communications Engineering dept. 5 2148
Giannis Papadopoulos wrote: I have the following code
#include <stdio.h>
void a(void) { printf("a called.\n"); }
int b(void) { printf("b called.\n");
return 0x1; }
int main(void) { void (*p)(void);
p = a; p(); p = b; p();
return 0; }
However, it does issue a warning that I am trying to assign a function of wrong type. Is there any portable way to say to the compiler "shut up, I know what I am doing?"
Yes, there is:
p = (void(*)(void))b;
However, you'd be telling a lie, because you *don't* know what
you're doing! The subsequent `p();' invokes undefined behavior,
because it uses a pointer of one type to call a function of a
different type. You wouldn't expect
double (*q)(const char*) = (double(*)(const char*))strlen;
double d = q("Hello, world!");
to work, would you? Well, the situation's no different in your
code: the pointer does not match the function, the compiler puts
together the wrong kind of function linkage, and anything can
happen.
And what is the most common way of declaring and using function pointers, the above or this?
p = &a; (*p)();
It's a matter of taste, I think. I seldom see `p = &a;',
perhaps for the same reason that `char *s = "Hello, world!";' is
more common than `char *s = &"Hello, world!"[0];'. As for the
call, on some pre-Standard compilers this form was required, and
coders who worked in those days may still use it out of habit.
Some may continue to do so just to make it clear that the call
is using a function pointer and not a literal function name; they
feel the code is more "self-documenting" if written this way.
I prefer to write `p();' instead of the more cluttered `(*p)();',
but the preference isn't a strong one.
--
Eric Sosman es*****@acm-dot-org.invalid
Eric Sosman wrote: Giannis Papadopoulos wrote:
I have the following code
#include <stdio.h>
void a(void) { printf("a called.\n"); }
int b(void) { printf("b called.\n");
return 0x1; }
int main(void) { void (*p)(void); p = a; p(); p = b; p();
return 0; }
However, it does issue a warning that I am trying to assign a function of wrong type. Is there any portable way to say to the compiler "shut up, I know what I am doing"?
Yes, there is:
p = (void(*)(void))b;
However, you'd be telling a lie, because you *don't* know what you're doing! The subsequent `p();' invokes undefined behavior, because it uses a pointer of one type to call a function of a different type. You wouldn't expect
double (*q)(const char*) = (double(*)(const char*))strlen; double d = q("Hello, world!");
to work, would you? Well, the situation's no different in your code: the pointer does not match the function, the compiler puts together the wrong kind of function linkage, and anything can happen.
Yes but all I want is to ignore the returning value.
And I need a function pointer to switch between the 2.
Hmm, maybe this would be better?
#include <stdio.h>
void a(void) {
printf("a called.\n");
}
int b(void) {
printf("b called.\n");
return 0x1;
}
static void c(void) {
b();
}
int main(void) {
void (*p)(void);
p = &a;
p();
p = &c;
p();
return 0;
}
--
one's freedom stops where others' begin
Giannis Papadopoulos http://dop.users.uth.gr/
University of Thessaly
Computer & Communications Engineering dept.
Giannis Papadopoulos wrote: Eric Sosman wrote: [... function pointer type must match type of called function ...] Yes but all I want is to ignore the returning value. And I need a function pointer to switch between the 2.
The issue is that the type of the function's value is
part of the "signature," and can influence the way the function
is called and the way its returned value (if any) is retrieved.
For example, some implementations compile
struct foo func(void) {
struct foo f;
...
return f;
}
...
struct foo f2 = func();
as if it had been written
void func(struct foo* _value_ptr) {
struct foo f;
...
*_value_ptr = f;
}
...
struct foo f2;
struct foo _returned_struct;
foo(&_returned_struct);
f2 = _returned_struct;
to avoid the need to find a "secret place" (stack, register,
whatever) that's suitable for holding a possibly large struct.
If you call such a function through a `(void(*)(void))' pointer,
the compiler will not know it's supposed to generate the hidden
`_value_ptr' argument nor the hidden `_returned_struct' object
it should point to. Even if you intend to ignore the returned
value, it's obvious such a call is wrong and possibly fatal.
Now, on many machines it will turn out that the machinery
that calls a function returning `int' and ignores the returned
value is identical to the machinery that calls a `void' function.
This is partly accidental, but also partly intentional. In pre-
Standard C there was no `void', so the way one wrote what we'd
now describe as a `void' function was to write a function that
(formally speaking) was `int'-valued, even though it would not
actually return a value. The people who develop C compilers have
considerable incentive to see to it that as much old code as
possible continues to work, so there's an excellent chance that
you'll get away with your abuse of the language. However, it
is an abuse, and new code should avoid it. Someday, somebody
will find he can generate more efficient code if he does not
cater to practices that are more than fifteen years out of date,
and then where will you be? Don't Do That.
Hmm, maybe this would be better?
#include <stdio.h>
void a(void) { printf("a called.\n"); }
int b(void) { printf("b called.\n"); return 0x1; }
static void c(void) { b(); }
int main(void) { void (*p)(void);
p = &a; p(); p = &c; p();
return 0; }
This is fine. In fact, this is an excellent technique
for using pointers to call functions that may have widely
different argument and result types: You "wrap" each target
function in a "helper" function, and see to it that all the
helpers have the same type.
--
Eric Sosman es*****@acm-dot-org.invalid
On Mon, 05 Sep 2005 16:37:23 +0300, Giannis Papadopoulos
<ip******@inf.uth.gr> wrote: Eric Sosman wrote: Giannis Papadopoulos wrote:
I have the following code
#include <stdio.h>
void a(void) { printf("a called.\n"); }
int b(void) { printf("b called.\n");
return 0x1; }
int main(void) { void (*p)(void); p = a; p(); p = b; p();
return 0; }
However, it does issue a warning that I am trying to assign a function of wrong type. Is there any portable way to say to the compiler "shut up, I know what I am doing"?
Yes, there is:
p = (void(*)(void))b;
However, you'd be telling a lie, because you *don't* know what you're doing! The subsequent `p();' invokes undefined behavior, because it uses a pointer of one type to call a function of a different type. You wouldn't expect
double (*q)(const char*) = (double(*)(const char*))strlen; double d = q("Hello, world!");
to work, would you? Well, the situation's no different in your code: the pointer does not match the function, the compiler puts together the wrong kind of function linkage, and anything can happen.
Yes but all I want is to ignore the returning value.
But you can't. The compiler knows the code for any function called
via p returns nothing. Therefore, it can make assumptions about what
happens when such a function returns. For example, if int returns are
always done in register x, then register x will be unchanged. If
register x is used by code before and after the function call, then it
may not be necessary to reload its value.
In your case, after p=b this will no longer be true. b() changed the
value of register x but the compiler doesn't know it. It might
attempt to reuse the value of register x but now it will get the
residue from b().
And I need a function pointer to switch between the 2.
There are other techniques that don't lead to undefined behavior, such
as a wrapper function, if-then, changing a() so it always returns 0,
etc. Hmm, maybe this would be better?
#include <stdio.h>
void a(void) { printf("a called.\n"); }
int b(void) { printf("b called.\n"); return 0x1; }
static void c(void) { b(); }
int main(void) { void (*p)(void);
p = &a;
The & is superfluous.
p(); p = &c; p();
return 0; }
In the sense that it does not lead to undefined behavior, yes, it is
better.
<<Remove the del for email>>
On Mon, 05 Sep 2005 16:37:23 +0300, Giannis Papadopoulos
<ip******@inf.uth.gr> wrote: Eric Sosman wrote: Giannis Papadopoulos wrote:
I have the following code
#include <stdio.h>
void a(void) { printf("a called.\n"); }
int b(void) { printf("b called.\n");
return 0x1; }
int main(void) { void (*p)(void); p = a; p(); p = b; p();
return 0; }
However, it does issue a warning that I am trying to assign a function of wrong type. Is there any portable way to say to the compiler "shut up, I know what I am doing"?
Yes, there is:
p = (void(*)(void))b;
However, you'd be telling a lie, because you *don't* know what you're doing! The subsequent `p();' invokes undefined behavior, because it uses a pointer of one type to call a function of a different type. You wouldn't expect
double (*q)(const char*) = (double(*)(const char*))strlen; double d = q("Hello, world!");
to work, would you? Well, the situation's no different in your code: the pointer does not match the function, the compiler puts together the wrong kind of function linkage, and anything can happen.
Yes but all I want is to ignore the returning value.
But you can't. The compiler knows the code for any function called
via p returns nothing. Therefore, it can make assumptions about what
happens when such a function returns. For example, if int returns are
always done in register x, then register x will be unchanged. If
register x is used by code before and after the function call, then it
may not be necessary to reload its value.
In your case, after p=b this will no longer be true. b() changed the
value of register x but the compiler doesn't know it. It might
attempt to reuse the value of register x but now it will get the
residue from b().
And I need a function pointer to switch between the 2.
There are other techniques that don't lead to undefined behavior, such
as a wrapper function, if-then, changing a() so it always returns 0,
etc. Hmm, maybe this would be better?
#include <stdio.h>
void a(void) { printf("a called.\n"); }
int b(void) { printf("b called.\n"); return 0x1; }
static void c(void) { b(); }
int main(void) { void (*p)(void);
p = &a;
The & is superfluous.
p(); p = &c; p();
return 0; }
In the sense that it does not lead to undefined behavior, yes, it is
better.
<<Remove the del for email>> This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Roy Yao |
last post by:
Hello,
I need to pass a pointer to a
callback function to the lower
level modules. But the function
is thought to be a virtual member one.
How can I get the real address of
the virtual...
|
by: Jan-Henrik Grobe |
last post by:
Hallo,
I am coming to this newsgroup with a very strange Problem. I have two c++
files A.cpp and B.cpp....In A.cpp I am creating an openGL window and in
B.cpp I have stored the callback...
|
by: Edd |
last post by:
Hello all,
I've made a data structure and an associated set of functions to enable me
to store a dynamically-sized array of elements of whatever data type I like.
Well that's the idea anyway......
|
by: Alfonso Morra |
last post by:
How can this work ?
I have the following declarations in a header:
Header
=========
typedef void (*VFPTR)(void) ;
void FOO_Callback(void*, char*, char*, int, unsigned long, void*,void*);...
|
by: Alexei A. Frounze |
last post by:
Seems like, to make sure that a pointer doesn't point to an object/function,
NULL (or simply 0) is good enough for both kind of pointers, data pointers
and function pointers as per 6.3.2.3:
3 An...
|
by: I.M. !Knuth |
last post by:
Hi. I'm more-or-less a C newbie. I thought I had pointers under control until
I started goofing around with this:
...
|
by: Beta What |
last post by:
Hello,
I have a question about casting a function pointer. Say I want to make
a generic module (say some ADT implementation) that requires a function
pointer from the 'actual/other modules'...
|
by: aruna.mysore |
last post by:
Hi all,
I have a specific problem passing a function pointer array as a
parameter to a function. I am trying to use a function which takes a
function pointer array as an argument. I am too sure...
|
by: MikeC |
last post by:
Folks,
I've been playing with C programs for 25 years (not professionally -
self-taught), and although I've used function pointers before, I've never
got my head around them enough to be able to...
|
by: ghulands |
last post by:
I am having trouble implementing some function pointer stuff in c++
An object can register itself for many events
void addEventListener(CFObject *target, CFEventHandler callback,
uint8_t...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome former...
|
by: ryjfgjl |
last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
|
by: taylorcarr |
last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
|
by: aa123db |
last post by:
Variable and constants
Use var or let for variables and const fror constants.
Var foo ='bar';
Let foo ='bar';const baz ='bar';
Functions
function $name$ ($parameters$) {
}
...
|
by: ryjfgjl |
last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
|
by: BarryA |
last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
by: Sonnysonu |
last post by:
This is the data of csv file
1 2 3
1 2 3
1 2 3
1 2 3
2 3
2 3
3
the lengths should be different i have to store the data by column-wise with in the specific length.
suppose the i have to...
|
by: Hystou |
last post by:
There are some requirements for setting up RAID:
1. The motherboard and BIOS support RAID configuration.
2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
| |