How (*ptr_fun1)(10) and ptr_fun1(10) are same in the below code
Code:
#include<stdio.h>
void fun1(int a)
{
printf("It is %d\n",a);
}
int main()
{
void (*ptr_fun1)(int);
ptr_fun1 = fun1;
/*
ex-
ptr_fun1 fun1
+----+ +-----+
+1000+ +code +
+----+ +-----+
1234 1000
fun1(10); <=> ptr_fun1(10); //how
*/
printf("%d\n%d",ptr_fun1(10),(*ptr_fun1)(20));
return 0;
}
output
10
20
Can some one please explain how it works.
The syntax for declaring (and using) function pointers in C (and C++) is one of the most puzzling aspects of the language for beginners. I shall try to explain a little, here.
First, let's consider pointers to 'simple' types (we'll take the 'int' type as an example). In this case, declaring a variable of the type is trivial: int N; Also, declaring a pointer to an int is also trivial: int *pN;We can interpret this second declaration in terms of 'evaluating' the '*' operator, which means "get the object that resides at the given address." So, in int *pN we are declaring that "the object that lies at the address "pN" is an int.
For functions, this is not so simple! Take a case of a function that takes an int as its (only) argument and returns an int value: int IFunc(int arg);. This is also very straightforward.
But how could we declare a pointer to such a function? We cannot simply apply the same logic as for the 'simple' types (by preceding with a * operator), like this:
int *pIFunc(int arg);
Because this would declare a function that takes an int arg and returns a pointer to an int.
So, the early implementors of the C language had to come up with something better - and completely unambiguous. So they decided to use the syntax of putting the "*NAME" section in parentheses, to isolate that 'dereference' operation from the function's definition:
int (*pIFunc)(int arg);
So, when faced with anything that looks remotely like this: < typename > (*Name1)(...); (where < typename > is any allowable C-type, like int, void, double, or even 'compound' types such as int*, and the "..." inside the second set of brackets can be either empty or a list of other 'types'), recognize it as a declaration of a function pointer (or as dereferencing a function pointer). To get the underlying function 'signature' (or invocation), just remove the first set of brackets and the contained *. So, for:
(*ptr_fun1)(20)
you can read:
ptr_fun1(20)
And, for:
void (*ptr_fun1)(int);
you can see that ptr_fun has the following signature:
void ptr_fun1(int);
I hope this makes things a bit clearer. Feel free to ask for further clarification and/or explanations.
The following code is valid C:
typedef int math_op(int, int); // Function type definition
The only time I've ever seen a function type declared and then used is in the case where we make a statement like the following:
math_op *mOp = add;
where add may be:
int add(int a, int b)
{
return a + b;
}
The following compiles as well given the initial declaration:
math_op mOp;
However, here it is not declared as a function pointer, but as a function itself. However, I know no actual usage for this and find it to be quite confusing because it seems we're declaring a function with no actual definition.
My question is, is there any other usage for a typedef'd function aside from using it as a function pointer type like this? Note that I am already aware of the alternative function pointer type syntax typedef int (*math_op)(int,int); which creates a function pointer type, whereas my original syntax above creates a function type to which we later point to.
According to clang:
error: non-object type 'math_op' (aka 'int (int, int)') is not
assignable: math_op tee = 0;
So that really limits our options.
The only use I can find is if you want to forward declare a bunch of functions with the same type signature. This is probably not a good idea and would probably increase the WTF's / line of your code.
math_op tee;
int tee (int x, int y) {
return x + y;
}
int (*)[3] foo (); doesn't work.
How to declare function return pointer to array of 3?
It might not be useful, but I want to know if it's possible.
First, I agree with the other answers that you probably need a typedef or a struct in there to clarify.
If you want to know how to declare the return type, it's
int (*foo(void))[3] {
In the "declaration reflects use" pattern, you can build this up by considering the usage, i.e. how to get from foo's type to the plain type int:
take foo
call it (with no arguments): foo()
dereference the return value: *foo()
add an array index: (*foo())[i]; the parentheses are needed because the postfix syntax would otherwise take precedence over prefix one.
the result is of plain type int
Declaration reflects it:
take foo
call it: foo(void), inserting void to say it's specifically a 0-param function rather than one with an unspecified set of parameters
dereference the function return value: *foo(void)
add an array index: (*foo(void))[3], making the "index" be the size of the array
we got down to the plain type, so declare that the thing you built has that type: int (*foo(void))[3]
Example code:
#include <stdio.h>
int arr[3];
int (*foo(void))[3] {
return &arr;
}
int main (void) {
arr[0] = 413;
arr[1] = 612;
arr[2] = 1025;
printf("%d %d %d\n", (*(foo()))[0], (*(foo()))[1], (*(foo()))[2]);
return 0;
}
Side note: be sure that the array you are returning a pointer to will continue to exist after the function returns.
I'd advise against doing this.
It's often done as a poor workaround for the apparent limitation that C has of not being able to have an array as a return value.
Too often, a dangling pointer will be returned since the programmer will return a pointer to an array in the function that has automatic storage duration. Then this gets hacked to a static which ruins the threading model and breaks all previous returned pointers!
Only slightly better is returning a pointer given to you by a malloc call internal to the function. But then, that burdens (asymmetrically) the caller with having to call free at some point. Eventually your function winds up in some kind of precompiled library which uses a different C runtime to a client. Your malloc and their free no longer match, and you end up with a truck load of undefined behaviour!
Instead of all this, do consider passing the array by pointer on the function parameter list, preferably pre-allocating the memory.
One way is:
typedef int Int_array_3[3];
Int_array_3 * foo(void);
As a rule of thumb, avoid functions passing/returning raw array pointers or function pointers, because such code is a nightmare both to program and read. In this case it would have been
int (*func()) [3]
which is completely unreadable. Just forget about writing such code. Instead, use a typedef to define an array type:
typedef int iarr3_t [3];
And then write a function returning a pointer to such an array:
iarr3_t* func (void);
However, as indicated by other comments and answers, returning an array pointer is usually quite questionable practice to begin with. The need to do so could be an indication of poor program design.
I'm having problems understanding the syntax of a pointer to a function using typedef. I've read a lot of answers but still couldn't understand something.
I'll try to explain how I see things so you could understand my thinking.
So we use typedef to give aliases to existing types for example :
typedef int number;
Will make it so we could use a number same as an integer (similar to preprocessor directives - I know there're some differences like when making a typedef of a pointer).
Another example :
typedef struct
{
int num;
} MyStruct;
Will give the unnamed structure an alias named MyStruct.
So Here's the syntax of a pointer to function typedef:
typedef int (*pFunc)(int, int);
Maybe I'm having hard time to understand this since typedef is like it's name giving aliases to TYPES and a function is not exactly type but anyway, from my understanding this is more of a pointer to some sort of a function signature, so the first int is the returned type, the second parenthesis are to indicate what types are the arguments being passed to the function.
Now what I don't quite understand is this part :
(*pFunc)
What I think it is, is that we create a new type (using typedef)
named pFunc that is a pointer and that's the role of the *. Now we
could create variables of this type that will point to ANY function
with the signature we described. Am I correct ?
Ok, say I'm correct, usually pointers to some memory are declared as follow :
int *p;
double *p;
.
.
.
So wouldn't it make more sense to do it as follow :
(pFunc*)
Because to me it looks like if the asterisk is before the name it looks like pFunc is a variable name of type pointer of some type and not an actual type pointer.
Can we do that ^ ? If so, is it commonly used to put the asterisk
after and not before ? If it's more common to put it before then why
is that ? Because like I said when we define a pointer type we always
put the asterisk after the name itself like the examples above so why
is that exactly ?
Another question regarding to this, I don't quite understand what are
the job of the parenthesis around *pFunc.
I think that they're used to indicate that pFunc type pointer of something and if we wouldn't do put parenthesis then the return type
of the signature will be of type int* instead of just int, am I
correct here ?
Ok, another thing that bothers me about it as the order of the syntax.
So far, in all typedef definitions we had the type on the left and the alias(es) on the right.
typedef int number;
typedef struct
{
int num;
} MyStruct;
We see that the int and the struct are the types which are being on the left and the alias we gave them are on the right.
Now, in pointers to function typedef it doesn't follow this convention.
We have the type returned of the function on the right then the typename in parenthesis then the type of the arguments in parenthesis, this order makes me confused after looking on how the other typedef are working on the same order.
Wouldn't it make more sens to do something like this ? :
typedef int (int,int) Func; So we have a typedef first, the type we want to give alias(es) to, which in this case is a function
signature which takes 2 ints and return an int, and then on the right
we have the alias name. Won't it make more sense ? this follows the
other typedef order, I just don't get the function pointer order that
much ..
Another question of mine : When we make a pointer to a function, what
does it actually mean ? I understand we can call this function using
our alias but pointers like variables are stored in a memory address
? What is there to store for a function ?
Lastly, I've read that the keyword extern has something to do with
pointers to function but couldn't understand what this keyword does,
could someone explain to me what it does ?
The typedef uses the same syntax for declaring types as would normally be used for declaring values.
For instance, if we declare an int called myInt, we do:
int myInt;
If we want to declare a type called myIntType to be an int, we simply add typedef:
typedef int myIntType;
We can declare a function myFunc, as follows:
int myFunc(int a, int b);
Which tells the compiler that there is an actual function with that name and signature that we can call.
We can also declare a function type myFuncType by doing:
typedef int myFuncType(int a, int b);
And we could do:
myFuncType myFunc;
Which is equivalent to the previous declaration of myFunc (although this form would rarely be used).
A function is not a conventional value; it represents a block of code with an entry point address. Function declarations like those above are implicitly extern; they tell the compiler that the named thing exists somewhere else. However, you can take the address of a function, which is called a function pointer. A function pointer can point to any function with the correct signature. A pointer is declared by prefixing the name of the type/value with a *, so, we might try:
int *myFuncPtr(int a, int b);
But this would be incorrect because the * binds more tightly with the int, so we have declared that myFuncPtr is a function that returns a pointer to an int. We must put parens around the pointer and name to change the binding order:
int (*myFuncPtr)(int a, int b);
And to declare a type, we simply add typedef to the front:
typedef int (*myFuncPtrType)(int a, int b);
In the declaration of myInt above, the compiler allocated some memory for the variable. However, if we were writing some code in a different compilation unit, and wanted to reference myInt, we would need to declare it as extern (in the referencing compilation unit) so that we reference the same memory. Without the extern, the compiler would allocate a second myInt, which would result in a linker error (actually that's not quite true because C allows tentative definitions, which you shouldn't use).
As noted above, functions are not normal values, and are always implicitly extern. However, function pointers are normal values, and need the extern if you are trying to reference a global function pointer from a separate compilation unit.
Normally, you would put externs for your global variables (and functions) into a header file. You would then include the header into the compilation units that contain the definitions of those variables and functions so that the compiler can make sure the types match.
The syntax for a variable definition or declaration is the type followed by one or more variables possibly with modifiers. Some simple examples would be:
int a, b; // two int variables a and b
int *a, b; // pointer to an int variable a and an int variable b
int a, *b, **c; // int variable a, pointer to an int variable b, and pointer to a pointer to an int variable c
Notice that in all of these the asterisk modifies the variable to the right of the asterisk, changing it from an int into a pointer to an int or a pointer to a pointer to an int. The variables defined might be used like:
int a, *b, **c, d;
a = 5; // set a == 5
b = &a; // set b == address of a
c = &b; // set c == address of b which in this case has the address of int variable a
d = **c; // put value of a into d using pointer to point to an int variable a
d = *b; // put value of a into d using pointer to an int variable a
d = a; // put value of a into d using the variable a directly
The extern statement
The extern statement is used to indicate that the definition of a variable is located in some other file and that the variable has global visibility. So you can declare a variable using the extern keyword to be explicit about a variable so that the C compiler will have the information it needs to do a good level of checking when compiling. The extern indicates that the variable is actually defined with its memory allocation somewhere other than the file where the source using the variable is located.
Using typedef
The typedef is a very nice feature of modern C because it allows you to create an alias that amounts to a kind of halfway new type. To have the full capability of creating a new type really requires the class type features of C++ which allows the definition of operators for the new type as well. However typedef does provide a good way of allowing a programmer to create an alias for a type.
Most uses of typedef are to provide a way to make it shorter and cleaner to write a variable definition. It is used a lot with struct definitions for that reason. So you might have a struct definition like the following:
typdef struct {
int iA;
int iB;
} MyStruct, *PMyStruct;
This will create two new aliases for the struct, one for the struct itself and one for a pointer to the struct and these might be used like:
MyStruct exampleStruct;
PMyStruct pExampleStrut;
pExampleStruct = &exampleStruct;
This example has the basic structure of typedef keyword, definition of the new type in terms of existing types, and name of the new type.
Old style C before typedef
Years ago in the older C compiler days before typedef was added to the C standard, people would often use the C Preprocessor to define macros to create an alias for a complex type. typedef is a much cleaner way of doing it!
Before typedef was added to the C standard, you would specify a tag for the struct and the result would be code that looked like this:
struct myTagStruct { // create a struct declaration with the tag of myTagStruct
int a;
int b;
};
struct myTagStruct myStruct; // create a variable myStruct of the struct
At which pointer people would usually add a C Preprocessor define to make it easier to write as in:
#define MYTAGSTRUCT struct myTagStruct
and then use it something like:
MYTAGSTRUCT myStruct;
However there is one major difference between using the preferred typedef syntax rather than the Preprocessor define approach. The Preprocessor works with the text of the C source code file to generate a modified version of the C source which is then compiled by the C compiler. The typedef keyword is part of the C source compiled by the C compiler so the C compiler knows about the type alias defined.
To show the difference, see the following source code.
#define PMYSTRUCT MyStruct *
typedef struct {
int a1;
int b1;
} MyStruct, *PMyStruct;
MyStruct sA, sB; //
PMyStruct psA, psB; // compiler sees this as MyStruct *psA, *psB;
PMYSTRUCT psxA, psxB; // Preprocessor generates MyStruct * psxA, psxB;
psA = &sA;
psB = &sB;
psxA = &sA;
psxB = &sB; // compiler error - psxB is not a pointer variable
Using typedef with function pointers
The syntax of typedef for function pointers is a bit unusual. It looks somewhat like a function declaration but does have a slight twist with an additional pointer syntax.
typedef int (*pFunc)(int a1, int b1);
This says the following:
create a typedef for a variable type pFunc
a variable defined as a pFunc type is a pointer
what the variable points to is a function with two int arguments that returns an int
The parenthesizes are important because they force the compiler to interpret the source text in a way different from the default rules. The C compiler has rules that it uses to parse the source text and you can change the way that the C compiler interprets the source text by using parenthesizes. The rules have to do with the parsing and how the C compiler locates the variable name and then determines the type of the variable by using rules about left and right associativity.
a = 5 * b + 1; // 5 times b then add 1
a = 5 * (b + 1); // 5 times the sum of b and 1
int *pFunc(int a1, int b1); // function prototype for function pFunc which returns a pointer to an int
int **pFunct(int a1, int b1); // function prototype for function pFunc which returns a pointer to a pointer to an int
int (*pfunc)(int a1, int b1); // function pointer variable for pointer to a function which returns an int
int *(*pFunc)(int a1, int b1); // function pointer variable for pointer to a function which returns a pointer to an int
A function prototype is not a function pointer variable. The syntax of a typedef is similar to the syntax for a variable definition that is not using a typedef.
typedef int * pInt; // create typedef for pointer to an int
int *a; // create a variable that is a pointer to an int
pInt b; // create a variable that is a pointer to an int
typedef int (*pIntFunc)(int a1, int b1); // create typedef for pointer to a function
typedef int *pFuncWhat(int a1, int b1); // create a typedef for a function that returns a pointer to an int. seems to be legal but useful? doubt it.
int (*pFuncA)(int a1, int b1); // create a variable pFuncA that is a pointer to a function
int *FuncDecl(int a1, int b1); // declare a function that returns a pointer to an int
pIntFunc pFuncB; // create a variable pFuncB that is a pointer to a function
So what does it mean to have a pointer to a function? A function entry point has an address because a function is machine code that is located at a particular memory area. The address of the function is where the execution of the functions machine code is supposed to start.
When the C source code is compiled, a function call is translated into a series of machine instructions which jump to the address of the function. The actual machine instructions are not really a jump but are instead a call instruction which saves the return address before it makes the jump so that when the called function completes it can do a return back to where it was called from.
A function pointer variable is used like a function statement. The difference between the two is similar to the difference between an array variable and a pointer variable. An array variable is treated like a constant pointer to a variable by most C compilers. A function name is treated like a constant pointer to a function by most C compilers.
Using a function pointer
What a function pointer does give you though is flexibility though it is flexibility that as with any great power can also lead to great ruin.
One use of function pointer variables is to pass a function address as an argument to another function. For instance the C Standard library has a couple of sort functions that require an argument of a collation function for comparing two elements being sorted. Another example would be a threading library that when you create a thread, you specify the address of the function to be executed as a thread.
Since a function pointer is a variable then if you have a function pointer that needs global visibility when you declare the variable for files other than the source file where it is actually defined and its memory allocated you would use the extern keyword as part of the function pointer variable declaration. However if it is a variable that is allocated on the stack within a function or if it is used within a struct to create a member of the struct then you would not use the extern modifier on the variable.
file1.c
// define a function that we are going to make available
// through a function pointer. a function will have global
// visibility unless we use the static keyword to reduce the
// visibility to this source file.
static int myfunc(int a, float b)
{
return (a + (int) (b * 100.0));
}
// define a function pointer that contains the address of the
// function above that we are exporting from this file.
// this function pointer variable automatically has global visibility
// due to where the statement is located in the source file.
int(*pmyfunc)(int, float) = myfunc;
file1.h
// declare the function pointer, which has global visibility
// due to where it was defined in the source file. we declare
// the function pointer in an extern in order to make the
// function prototype with argument types available to the compiler
// when using this variable in other source files.
extern int(*pmyfunc)(int, float);
file 2.c
#include "file1.h"
int iifunc (int a, int b)
{
return (a + b/10 + 5);
}
// define a function that has as an argument a function pointer
// variable. this allows the caller to inject into the processing
// of this function a function to be used in the function.
int jjfunc (int a, int (*pf)(int, float))
{
return ((a / 10) + pf(a, 2000.0));
}
int kkfunc (int a, char *pName)
{
// an example of a local definition of a function pointer.
// we could have used pmyfunc directly.
int(*plocalfunc)(int, float) = pmyfunc;
// following two statements show difference between calling a
// function with a function pointer argument and calling a
// function with a function call in the argument list.
int k = jjfunc(a, plocalfunc);
int l = iifunc(a, pmyfunc(a, 3000.0));
printf ("%s - %d\n", pName, k);
return k;
}
Another case is to provide some kind of interface that hides implementation details. Let's say that you have a print function that you want to use for several different output sinks or places where the output to go, say a file, a printer, and a terminal window. This is similar in nature to how virtual functions are implemented by C++ compilers or how COM objects are implemented through a COM interface. So you could do something like the following which is a very simple example missing details:
typedef struct {
int (*pOpenSink) (void);
int (*pPrintLine) (char *aszLine);
int (*pCloseSink) (void);
} DeviceOpsStruct;
DeviceOpsStruct DeviceOps [] = {
{PrinterOpen, PrinterLine, PrinterClose},
{FileOpen, FileLine, FileClose},
{TermOpen, TermLine, TermClose}
};
int OpenDevice (int iDev)
{
return DeviceOps[iDev].pOpenSink();
}
int LineDevice (int iDev, char *aszLine)
{
return DeviceOps[iDev].pPrintLine (aszLine);
}
int CloseDevice (int iDev)
{
return DeviceOps[iDev].pCloseSink();
}
Just to make clear the explanation given by others, in C/C++, the parenthesis are right associative, therefore the following declaration:
typedef int *pFunc(int, int);
is equivalent to:
typedef int *(pFunc(int, int));
which would be the declaration prototype of a function returning a pointer to an integer and not the declaration of a pointer to a function returning an integer.
This is why you need to write the parenthesis around (*pFunc) to break the right association and tell the compiler that pFunc is a pointer to a function and not simply a function.
I was grabbing information about pointers to functions when I found this declaration:
char (* ( *f())[])();
I tried to find out what is the meaning of it but I couldn't...
what does it refer to?
It breaks down as follows:
f -- f
f() -- is a function returning
*f() -- a pointer to
(*f())[] -- an array of
*(*f())[] -- pointer to
(*(*f())[])() -- function returning
char (*(*f())[])(); -- char
Postfix operators like [] and function call () bind before unary operators like *, so
*a[] -- is an array of pointer
(*a)[] -- is a pointer to an array
*f() -- is a function returning a pointer
(*f)() -- is a pointer to a function
Find the leftmost identifier and work your way out, applying those rules recursively for any function parameters.
Edit
In the comment to another answer, KerrekSB suggests using typedefs, which would certainly make the code scan more easily:
typedef char CharFunc();
typedef CharFunc *CharFuncPtr;
typedef CharFuncPtr CharFuncPtrArr[N];
typedef CharFuncPtrArr *CharFuncPtrArrPtr;
typedef CharFuncPtrArrPtr CharFuncPtrArrPtrFunc();
CharFuncPtrArrPtrFunc *f;
You could probably come up with a better naming convention. But even so,
CharFuncPtrArrPtrFunc *f;
sure looks nicer than
char (*(*f())[])();
But is it better?
In my experience, the answer is often "no", especially when pointer types are involved. What is the function that f points to supposed to look like? How do I call it? What parameters am I supposed to pass to it? What do I do with the value returned by the function f points to? How do I use it in an expression? I have to look up the definition of CharFuncPtrArrPtrFunc, which means I also have to look up the definition of CharFuncPtrArrPtr, and CharFuncPtrArr, etc., etc., etc., then I have to mentally puzzle out the resulting syntax for the call.
char (*(*f())[])(); borders on total unreadability, but it tells me at a glance how I should call the function f points to and how to use the return value.
declare f as function returning pointer to array of pointer to function returning char