This question already has answers here:
How do function pointers in C work?
(12 answers)
Closed 9 years ago.
In a book, I came across the following question.
The problem which I am facing is, what is a function pointer? How does it work and what is the syntax for it's declaration.
Point the error in given code.
main()
{
int (*p)()=fun;
(*p)();
}
fun()
{
printf("Hi..");
}
my first question is, What does following code snipet signifies?
int (*p)()=fun;
(*p)();
and second obvious question what is the error in the given code..??
refer to ionela.voinescu's answer for solution.. it is same as that written in solution manual..thnx
int (*p)() = fun declares a pointer to a function that returns int, then assigns the address of the function fun to that pointer. (*p)() calls whatever function p is pointing to.
Problems with your code:
fun and main should have a return type. Your compiler might not demand it and assume they return ints, but you should give them one nonetheless.
You need to declare fun above main, or use a prototype
Also, (*p)() is unnecessary; you can just use p().
As a side note, because function pointer syntax is relatively ugly, it's fairly common to see typedefs such as
typedef int(*IntFunc)();
which would allow you to declare and use p like so:
IntFunc p = fun;
p();
The correct code is the following:
#include <stdio.h>
int fun();
int main(){
int (*p)()=fun;
(*p)();
return 0;
}
int fun(){
printf("Hi..");
return 0;
}
1.
int fun();
You have to declare your function before using it in main; Otherwise main wont recognize it.
2.
int (*p)() : Declaration of a variable p which is a pointer to a function that returns int and has no arguments(or undefined number of arguments, depending on the standard).
3.
int fun();
.........
int (*p)()=fun;
In order for this to work fun must also return int. Meaning when assigning a value to a variable this must have a type which corresponds with the declaration of the variable. When assigning a value to a pointer to a function that returns int and has no arguments the function assigned to it must also return int and have no arguments (or undefined number of arguments, depending on the standard).
4.
(*p)();
You call the function p which now points to fun.
fun is name of the the function itself.
int (*p)()
is the definition of the function pointer like 'int a' is the definition of an integer.
int * is the pointer itself, () means it is a pointer to a function.
(*p)();
This is the execution of the function of the function pointer p, i.e. p is assigned to the function fun, which is executed by calling the content of the pointer p, thus (*p)();
Related
I found this question on an online exam. This is the code:
#include <stdio.h>
int main(void) {
int demo();
demo();
(*demo)();
return 0;
}
int demo(){
printf("Morning");
}
I saw the answer after the test. This is the answer:
MorningMorning
I read the explanation, but can't understand why this is the answer.
I mean, shouldn't the line int demo(); cause any "problem"?
Any explanation is helpful. Thanks.
It is not a problem because that int demo(); is not a function definition, it is just an external declaration, saying (declaring) that a function of such name exists.
In C you cannot define a nested function:
int main(void) {
int demo() {} //Error: nested function!!!
}
But you can declare a function just fine. It is actually equivalent to:
#include <stdio.h>
int demo(); //function declaration, not definition
int main(void) {
demo();
(*demo)();
return 0;
}
int demo(){
printf("Morning");
}
except that in your code the external forward demo() declaration is only visible inside main.
You can declare a function inside another function. This is allowed. The only thing is it is visible only inside the function in which it is declared.
Other answers didn't explain the
(*demo)();
part. Here's a partial explanation:
demo (without parentheses) is the function pointer. So you can first dereference it to get a function then call it with parentheses (wrapping the dereferenced object into parentheses else it means that you want to dereference the return value of the function)
So it's strictly equivalent to
demo();
(the notation is useful when the function pointer is stored in a variable, here it's just more cryptic than necessary)
int main(void) { int demo(); /*...*/ }; int demo(){ /*...*/ }
is equivalent to
int main(void) { extern int demo(); /*...*/ }; int demo(){ /*...*/ }
It declares the demo function with external linkage, inside the main function.
The demo identifier will be valid till the end of the scope, but demo will be a
normal, external function.
Unfortunately, you cannot do this for functions that are static, because
the standard (http://port70.net/~nsz/c/c11/n1570.html#note30) makes things like
int main(void) { static int demo(); } static int demo(){ /*...*/ }
illegal.
As to why (*demo)(); works and is in this context equivalent to demo(); or (&demo)(); or (*&demo)();:
After you declare demo with int demo();, demo is a function designator (which is not the same as a function pointer, not unlike an array designator is not the same as a pointer the the array's first element). Like arrays, though, function designators almost always decay to function pointers (see 6.3.2.1p4) and this type of decay happens in function calls too. Essentially demo(); decays demo to a pointer and then calls
the function pointer. Applying * to such a pointer yields again the function designator which again decays to a pointer to make the call.
Admittedly, all this stuff is very weird and esoteric and I can't even think of a situation where the distinction is useful. IMHO, it's probably best to stick to demo(); or (demo)() (if you want to supress macro expansion) and never use (*demo)() (at least not on functions -- on function pointers it is at least somewhat informative) and especially not (&demo)() as it serves little purpose other than to confuse the reader.
I am trying to understand what this means, the code I am looking at has
in .h
typedef void (*MCB)();
static MCB m_process;
in .C
MCB Modes::m_process = NULL;
And sometimes when I do
m_process();
I get segmentations fault, it's probably because the memory was freed, how can I debug when it gets freed?
It defines a pointer-to-function type. The functions return void, and the argument list is unspecified because the question is (currently, but possibly erroneously) tagged C; if it were tagged C++, then the function would take no arguments at all. To make it a function that takes no arguments (in C), you'd use:
typedef void (*MCB)(void);
This is one of the areas where there is a significant difference between C, which does not - yet - require all functions to be prototyped before being defined or used, and C++, which does.
It introduces a function pointer type, pointing to a function returning nothing (void), not taking any parameters and naming the new type MCB.
The typedef defines MCB as the type of a pointer to a function that takes no arguments, and returns void.
Note that MCB Modes::m_process = NULL; is C++, not C. Also, in C, the typedef should really be typedef void (*MCB)(void);.
I'm not sure what you mean by "the memory was freed". You have a static pointer to a function; a function cannot be freed. At most, your pointer has been reset somewhere. Just debug with a memory watch on m_process.
Let's take an example
typedef void (*pt2fn)(int);
Here, we are defining a type pt2fn. Variables of this type point to functions, that take an integer as argument and does not return any value.
pt2fn kk;
Here, kk is a variable of type pt2fn, which can point to any function that takes in an integer as input and does not return any value.
Reference:https://cs.nyu.edu/courses/spring12/CSCI-GA.3033-014/Assignment1/function_pointers.html
It's a function pointer. You get a SEGMENTATION FAULT because you are trying to make a call to a function which address is invalid (NULL).
According to your specific sample, the function should return no value (void) and should receive no parameters ().
This should work:
void a()
{
printf("Hello!");
}
int main(int arcg, char** argv)
{
m_process = a;
m_process(); /* indirect call to "a" function, */
// Hello!
}
Function pointers are commonly used for some form of event handling in C. It's not its only use though...
I'm trying to understand a code which have the following lines:
void terminate_pipe(int);
code code code...
struct sigaction new_Sigiterm;
new_Sigiterm.sa_handler = terminate_pipe;
My question are:
What is the meaning of calling a function like this? Is it going to
just put NULL as the parameter?
It is void, so new_Sigiterm.sa_handler will be NULL no matter what?
thanks.
new_Sigiterm.sa_handler is most likely a pointer that points to a function. By running
new_Sigiterm.sa_handler = terminate_pipe;
It's similar to saying
new_Sigiterm.sa_handler = &terminate_pipe;
(Like in pointers). This is not running the function, it's just making a pointer that points to the function, if you "run" the pointer, the pointed function will run.
This is how to declare function pointer:
void function(int x);
int main()
{
//Pointer to function
void (*foo) (int);
//Point it to our function
foo = function;
//Run our pointed function
foo(5);
}
More info about function pointers
Code like this assignment is setting a handler (sometimes called a function pointer): Basically, the address of the function to run, at a given time.
The syntax for this in C is to name the function, but don't put () on the end. That returns the address of the function.
new_Sigiterm.sa_handler = terminate_pipe;
void terminate_pipe(int); is not calling of function it is Forward declaration of function.
In new_Sigiterm.sa_handler sa_handler is a Function Pointer.
This question already has answers here:
what does it mean to convert int to void* or vice versa?
(6 answers)
Closed 9 years ago.
#include <stdio.h>
void pass(void* );
int main()
{
int x;
x = 10;
pass((void*)x);
return 0;
}
void pass(void* x)
{
int y = (int)x;
printf("%d\n", y);
}
output: 10
my questions from the above code..
what happens when we typecast normal variable to void* or any pointer variable?
We have to pass address of the variable to the function because in function definition argument is pointer variable. But this code pass the normal variable ..
This format is followed in linux pthread programming... I am an entry level C programmer. I am compiling this program in linux gcc compiler..
I'm only guessing here, but I think what you are supposed to do is actually pass the address of the variable to the function. You use the address-of operator & to do that
int x = 10;
void *pointer = &x;
And in the function you get the value of the pointer by using the dereference operator *:
int y = *((int *) pointer);
Please read why glib provide macros for this kind of conversions, there's no need to repeat the text here. The main point is: a pointer has a platform dependent size.
If you are planning to use pthreads and you are planning to pass the pass function to pthread_create, you have to malloc/free the arguments you are planning to use (even if the threaded function just need a single int).
Using an integer address (like &x) is probably wrong, indeed each modification you will execute on x will affect the pass behaviour.
I don't understand why the following code generates a warning:
int func(double a, int b, char c)
{
return 0;
}
int main()
{
int(*myPointer)() = func;
return 0;
}
I thought that in C, a function with an empty parameters list mean a function that can receive an unknown number of parameters. func4 happens to receive 3 parameters. So why is it incompatible with myPointer?
Its especially confusing because the following does compile without warning:
void boo()
{
return;
}
int main()
{
int(*pointerDude)(double) = boo;
return 0;
}
What's going on?
The difference between the two cases is explained like this: if you pass a parameter to a function that accepts none, you are just consuming some memory on the stack. If you don't pass any parameter to a function that accepts a few, the latter is going to read random data from the stack.
Update: changed to community wiki to add these corrections from Pascal Cuoq:
Casts of function pointer in both directions are legal, informative warnings from the compiler notwithstanding. Calling a function with the wrong prototype is illegal in both cases. Some ABIs mandate that the function clean up the stack, in which case passing parameters to functions that accept none corrupt the stack as surely as not passing parameters to functions that expect them.
C99 6.3.2.3 par. 8:
A pointer to a function of one type may be converted to a pointer to a
function of another type and back again; the result shall compare
equal to the original pointer. If a converted pointer is used to call
a function whose type is not compatible with the pointed-to type, the
behavior is undefined
This is the warning you get:
warning: initialization from incompatible pointer type
You are passing void which means that will require a cast. You should use the right types.
IIRC C compiler has certain assumptions which can cause very odd bugs because you're not telling it how much stack space it needs whenever that function is called. Especially since the definitions don't match this might allow someone to inadvertently read your function pointer declaration and assume no parameters and have the function return garbage. If you really want to take variable numbers of parameters use my_func(...) and varargs.
A warning is just that, a warning. Honest.
In that case, the compiler knows you have an incorrect function pointer type and it blatantly tells you that. If you try to pass a number of parameters different then 3, then it will be issued an error.
I think that the problem is related to the casting of the parameters, because char is not 32 bits. Note that if you change the char to int this works fine. It is related to automatic promotion of variables.
Compare the two:
int func();
int func(double a, int b, int c)
{
return 0;
}
and
int func();
int func(double a, int b, char c)
{
return 0;
}
gcc gives you warning for the second, but not for the first
In C an empty parameter list means that the function does not take any parameters. I believe you are confusing an empty parameter list with varargs.
Changing your first example to include the parameters will remove the warning.
int func(double a, int b, char c)
{
return 0;
}
int main()
{
int(*myPointer)(double, int, char) = func;
return 0;
}