1) I am currently trying to understand the following code, but I can't understand what void(*func)(void) means, I can understand that I am trying to save a the address of function named "function" from list0513, at void pointer func, but what does the casting (void) just before the equal sign mean?
// list0513.c
#include <dlfcn.h>
int main(void)
{
void *handle = dlopen("./list0513.so", RTLD_LAZY);
void (*func)(void) = dlsym(handle, "function");
(*func)();
dlclose (handle);
return 0;
}
According to the book, the function called "function" is called from the following script
// list0513dl.c
#include <stdio.h>
void function(void)
{
printf("Hello World\n");
}
2) but how do I make a list0513.so file? the only files I've made are .c files...
Thanks for reading this.
The declaration reads as follows:
func — func
*func — is a pointer to
(*func)( ) — a function taking
(*func)(void) — no parameters
void (*func)(void) — returning void
The func pointer is then initialized with the result of the dlsym call, which returns the address of the function ”function” in the library list0513.so.
General declaration rules for pointer types:
T *p; // p is a pointer to T
T *p[N]; // p is an array of pointer to T
T (*p)[N]; // p is a pointer to an array of T
T *f(); // f is a function returning a pointer to T
T (*f)(); // f is a pointer to a function returning T
In both declarations and expressions, the postfix [] subscript and () function call operators have higher precedence than unary *, so *f() is parsed as *(f()) (function returning pointer). To declare a pointer to an array or function, the * has to be explicitly grouped with the array or function declarator.
Declarations can get pretty complex - you can have an array of pointers to functions:
T (*a[N])(); // a is an array of pointers to functions returning T
or functions returning pointers to arrays:
T (*f())[N]; // f is a function returning a pointer to an array
or even pointers to arrays of pointers to functions returning pointers to arrays:
T (*(*(*a)[N])())[M];
You probably won’t see anything that hairy in the wild, though (unless you run across some old code of mine).
It is omitted a declare of function type. The full or expended version should like this:
// list0513.c
#include <dlfcn.h>
int main(void)
{
void *handle = dlopen("./list0513.so", RTLD_LAZY);
typedef void(*FUNC)();
FUNC func = dlsym(handle, "function");
func(); // call function
dlclose (handle);
return 0;
}
Related
So, I am just trying to wrap my head around "pointer function that returns a pointer to an array"... but to start off slowly, I had to understand this:
void Print(const char c){
printf("\nPrint: %c\n", c);
}
int main () {
void (*FunctionPointer)(const char);
FunctionPointer = &Print;
FunctionPointer('a');
}
Which I do - pretty easy to guess what is going on... FunctionPointer just points to the location where the Print function "resides". Instead of jumping to a specific memory address (stored on a register) of a specific function, I can now be more flexible and point to any function that I want to access.
But I am stuck with the following...
int main () {
int (*FunctionPointer())[];
}
Now it seems that the function that is pointed by FunctionPointer, can in fact return a pointer to an array of type int. The compiler accepts the second line - so far so good - and I also understand the concept... but I am getting stuck regarding the implementation.
FunctionPointer needs - once again, to point to a function. That function can indeed return a pointer that points to an array of type int... soooooo:
int *Array(){
int ar[2] = {5,6};
return ar;
}
int main () {
int (*FunctionPointer())[];
FunctionPointer = &Array;
}
However, the last piece of code is just not accepted by the compiler.... So, what gives?
With
int (*FunctionPointer())[];
you've declared FunctionPointer as a function returning a pointer to an array of int -- not a function pointer. You want
int *(*FunctionPointer)();
If you use [] here, you'll get an error, as functions can't return arrays -- arrays are not first class types -- and unlike with function parameters, arrays will not be silently converted to pointers when used as the return value of a function type. With that, you'll still get the warning
t.c:3:12: warning: function returns address of local variable [-Wreturn-local-addr]
return ar;
^~
which is pretty self-explanatory
You have declared the array of function pointers. Arrays can't be assignable. Functions can't return arrays. You might wish
int* (*FunctionPointer)();
FunctionPointer = &Array;
Function pointers are much easier when you use typedefs. You can simply use the same notation as "normal" data pointers.
// func is a function type. It has one parater and returns pointer to int
typedef int *func(const char);
// funcptr is a pointer to func
func *funcptr;
This question already has answers here:
How do function pointers in C work?
(12 answers)
Closed 9 years ago.
I'm learning C and I came to this expression:
void *(*routine)(void *)
I find it very confusing. Maybe it's a pointer...to a pointer... to a pointer?
If I wanted to pass this thing into a function, how would we manipulate it? I am trying to pass this routine construction as a parameter to a function that takes a void(*)(void)... but I am rather lost on what that actually means.
Start with the leftmost identifier and work your way out, remembering that absent explicit grouping with parentheses, [] and function call () bind before *, so
*a[N] is an N-element array of pointers
(*a)[N] is a pointer to an N-element array
*f() is a function returning a pointer
(*f)() is a pointer to a function
So,
routine -- routine
*routine -- is a pointer
(*routine)( ) -- to a function
(*routine)(void *) -- taking a single parameter of type void *
*(*routine)(void *) -- returning a pointer
void *(*routine)(void *) -- to void
void *(*routine)(void *);
declares a pointer to function that takes argument of type void * and returns pointer of type void *
Simple example:
#include <stdio.h>
void* foo(void* x) {
printf("Hello.");
}
int main(void) {
void *(*routine)(void *);
routine = foo; // assings foo to our function pointer
(*routine)(NULL); // invokes foo using this pointer
return 0;
}
outputs: Hello.
"If I wanted to pass this thing into a function" ~ here is example 2 for you:
#include <stdio.h>
void* foo(void* x) {
printf("Hello.");
}
typedef void *(*RoutinePtr)(void *); // alias to make your life easier
void routineInvoker(RoutinePtr routine) {
(*routine)(NULL); // invokes the routine
}
int main(void) {
RoutinePtr routine = foo; // creates a function pointer
routineInvoker(routine); // and passes it to our invoker
return 0;
}
I have the following code:
typedef void (*func_type)(int a, int b);
func_type func;
int main()
{
func = (func_type)GetProcAddress(NULL, "func");
}
This code works fine, but I would like to change func_type func; to void func(int a, int b); (because code completion shows "func_type" instead of "func" when typing the parameters).
But when I try to change this, the compiler tells me that in the main function "expression must be a modifiable lvalue". I tried to look online but did not find an answer to my problem.
Code becomes this:
typedef void (*func_type)(int a, int b);
void func(int a, int b);
int main()
{
func = (func_type)GetProcAddress(NULL, "func");
}
Functions in C behave similar to arrays. They both decay to pointers. Whenever function name is used it automatically decays to a pointer to this function. The exceptions are & and sizeof operators. Operator sizeof does not accept a function as operand. That is why foo and &foo are equivalent.
Functions itself are non-modifiable by design. Any attempt of modifying it i.e. by memcpy-ing to a function pointer is undefined behaviour.
Surprisingly, function call operator () does not take a function as operand but a pointer to a function.
Therefore, a function call
foo(1);
is actually
(&foo)(1);
Because foo decays to &foo before evaluation of the function call.
That is why one can interchangeably use functions and function pointer in function call operands.
void foo(int) { ... }
void (*bar)(int);
foo(1); // foo decays to &foo which is a function pointer
bar(2); // bar is already a function pointer
To solve the original problem I suggest keeping func be a function pointer, that initially points to some dedicated function but it can be overwritten later on:
typedef void func_type(int,int);
void default_func(int a, int b) { ... }
funt_type* func = default_func; // decays to &default_func !
int main()
{
func(1,2); // calls default_func
func = (func_type*)GetProcAddress(NULL, "func");
func(3,4); // calls func from dll/so
}
I've decided to use function types (not function pointer types) what is a bit un-orthodox. IMO, it make syntax more visually pleasing, and it is easier to parse by a human. Moreover, it is explicit about what is a pointer what is not.
typedef void (*func_type)(int a, int b); declares func_type to be a type that is a pointer to a function. Then func_type func; declares func to be a pointer. Your proposed alternative, void func(int a, int b); declares func to be a function.
Since you can assign to a pointer, func = …; works with the first declaration. Since you cannot assign to a function, func = …; does not work with the second declaration.
To declare func to be a pointer to a function without using a typedef, use void (*func)(int, int);.
I was reading this code on a website. I am fairly new to programming so please explain in a bit more detail.
#include <stdio.h>
// A normal function with an int parameter
// and void return type
void fun(int a)
{
printf("Value of a is %d\n", a);
}
int main()
{
// fun_ptr is a pointer to function fun()
void (*fun_ptr)(int) = &fun;
/* The above line is equivalent of following two
void (*fun_ptr)(int);
fun_ptr = &fun;
*/
// Invoking fun() using fun_ptr
(*fun_ptr)(10);
return 0;
}
Doubts-
I am not able to understand this type of declaration and assignment void (*fun_ptr)(int) = &fun;
I mean that if we declare a data type, then we do it like int a; and assign it as a=10; but here we are assigning it by writing (*fun_ptr)(10);. Kindly help.
Instead of this record
(*fun_ptr)(10);
you could just write
fun_ptr(10);
That is it is a function call of the function fun pointed to by the function pointer fun_ptr due to the initialization of that pointer in its declaration by the function address
void (*fun_ptr)(int) = &fun;
In turn this declaration could be written simpler like
void (*fun_ptr)(int) = fun;
because a function designator (in this case fun) used in expressions as for example an initializer is implicitly converted to pointer to the function.
You could use a typedef alias for the function type the following way
typedef void Func( int );
In this case the above declaration of the function pointer could look simpler like
Func *fun_ptr = fun;
Here is your program rewritten using a typedef for the function type of the function fun.
#include <stdio.h>
typedef void Func( int );
// Function declaration without its definition using the typedef
// This declaration is redundant and used only to demonstrate
// how a function can be declared using a typedef name
Func fun;
// Function definition. In this case you may not use the typedef name
void fun( int a )
{
printf("Value of a is %d\n", a);
}
int main(void)
{
// Declaration of a pointer to function
Func *fun_ptr = fun;
// Call of a function using a pointer to it
fun_ptr( 10 );
return 0;
}
Lets rewrite it a little bit, by using type-aliases and some comments:
// Define a type-alias names fun_pointer_type
// This type-alias is defined as a pointer (with the asterisk *) to a function,
// the function takes one int argument and returns no value (void)
typedef void (*fun_pointer_type)(int);
// Use the type-alias to define a variable, and initialize the variable
// This defines the variable fun_ptr being the type fun_pointer_type
// I.e. fun_ptr is a pointer to a function
// Initialize it to make it point to the function fun
fun_pointer_type fun_ptr = &fun;
// Now *call* the function using the function pointer
// First dereference the pointer, to get the function it points to
// Then call the function, passing the single argument 10
(*fun_ptr)(10);
Hopefully it makes things a little clearer what's going on.
Following is the meaning of two statments.
void (*fun_ptr)(int) = &fun; this is called declaring and initializing the fun_ptr in the same line , this is same as doing int a = 10;
(*fun_ptr)(10); is not assignment statement, it is invoking the function fun through function pointer fun_ptr.
you can also use typedef to create a new user defined out of function pointer and use as shown in above answer.
This is an advanced topic if you are new to programming, fun_ptr is a pointer to a function.
The declaration:
void (*fun_ptr)(int) = fun;
Means fun_ptr is a pointer to a function taking an int argument and returning void, initialize if with a pointer to the function fun. (you don't need the &)
The line:
(*fun_ptr)(10);
does not assign anything, it calls the function pointed to by fun_ptr, but is way to complex
fun_ptr(10);
As fun_ptr points to fun this is equivalant to `fun(10).
Using a function pointer has its use eg in a sort function where the comparison function is passed in as a function pointer so the sorting can be different between calls.
achieves the same thing and is much easier on the eyes.
This question already has answers here:
How do function pointers in C work?
(12 answers)
Closed 9 years ago.
I'm learning C and I came to this expression:
void *(*routine)(void *)
I find it very confusing. Maybe it's a pointer...to a pointer... to a pointer?
If I wanted to pass this thing into a function, how would we manipulate it? I am trying to pass this routine construction as a parameter to a function that takes a void(*)(void)... but I am rather lost on what that actually means.
Start with the leftmost identifier and work your way out, remembering that absent explicit grouping with parentheses, [] and function call () bind before *, so
*a[N] is an N-element array of pointers
(*a)[N] is a pointer to an N-element array
*f() is a function returning a pointer
(*f)() is a pointer to a function
So,
routine -- routine
*routine -- is a pointer
(*routine)( ) -- to a function
(*routine)(void *) -- taking a single parameter of type void *
*(*routine)(void *) -- returning a pointer
void *(*routine)(void *) -- to void
void *(*routine)(void *);
declares a pointer to function that takes argument of type void * and returns pointer of type void *
Simple example:
#include <stdio.h>
void* foo(void* x) {
printf("Hello.");
}
int main(void) {
void *(*routine)(void *);
routine = foo; // assings foo to our function pointer
(*routine)(NULL); // invokes foo using this pointer
return 0;
}
outputs: Hello.
"If I wanted to pass this thing into a function" ~ here is example 2 for you:
#include <stdio.h>
void* foo(void* x) {
printf("Hello.");
}
typedef void *(*RoutinePtr)(void *); // alias to make your life easier
void routineInvoker(RoutinePtr routine) {
(*routine)(NULL); // invokes the routine
}
int main(void) {
RoutinePtr routine = foo; // creates a function pointer
routineInvoker(routine); // and passes it to our invoker
return 0;
}