I have 2 functions that have same parameters and return type.
Like
int fun1(int a){
return a+1;
}
int fun2(int a){
return a+2;
}
I made a funtion pointer int(*funptr)(int).
And I want to use malloc and make funptr[0] to point fun1, and funptr[1] to point fun2.
So I tried like
int(*funptr)(int)=(int*)malloc(2*sizeof(funptr));
but it doesn't work. What can I do?
What I understand is you need an array of function pointers. Change
int(*funptr)(int)
to
int (*funptr)[2] (int)
and use funptr[0] = fun1; and funptr[1] = fun2;
Alternatively, if you must use allocated memory, you can use a pointer to function pointer
int (**funptr)(int);
and then use accordingly. For ease of use, do use typedef.
typedef int(*funptr)(int);
funptr * fp;
fp = malloc(2* sizeof*fp);
fp[0] = fun1;
fp[1] = fun2;
Just do a simple array of function pointers.
int (*f)[2](int);
f[0] = fun1;
f[1] = fun2;
Use typedefs if you think the declaration syntax is tricky.
Another thing, if you want you can use malloc instead if you want, but Don't cast malloc
Here you actually made a mistake. You should have casted to a function pointer and not an integer pointer. Well, you should not have casted at all. Here it what it should have looked like:
int (**f)(int) = malloc(2 * sizeof *f);
if(!f) { /* Handle error */ }
f[0] = fun1;
f[1] = fun2;
free(f);
You almost certainly do not want to allocate an array of functions pointers dynamically. Bad idea.
If you insist, then first of you must realize that malloc always returns an object pointer of type void*, which is incompatible with function pointers. As is your current senseless cast to int*. So you need to go to some well-defined middle ground in between function pointers and object pointers, like a uintptr_t integer.
It is getting tedious to over and over again tell people to use typedef when working with function pointers, so I'm not gonna do that yet again. This will be messy even with such a typedef.
Given typedef int func_t (int);, an array of function pointers is func_t* arr[2];. However, since you use malloc, you actually need to use a pointer to such an array: func_t* (*funptr)[2].
The malloc call will be malloc(sizeof(func_t*[2])). However, as mentioned you need to cast the result into something that isn't an object pointer and pray that it's still portable: (uintptr_t)malloc(sizeof(func_t*[2]));. This is the least questionable I can come up with.
Then you must cast that one to a pointer to array of function pointer type. (func_t*(*)[2]).
The abomination end result:
typedef int func_t (int);
int main (void)
{
func_t* (*funptr)[2] = (func_t*(*)[2]) (uintptr_t)malloc(sizeof(func_t*[2]));
(*funptr)[0](1);
(*funptr)[1](1);
free(funptr);
}
You cant index function pointers. You need to declare the array of function pointers or pointer to pointer to function
int fun1(int a){
return printf("%s\n",__FUNCTION__);
}
int fun2(int a){
return printf("%s\n",__FUNCTION__);
}
typedef int func(int);
int main()
{
func *farr[2];
farr[0] = fun1;
farr[1] = fun2;
for(int x = 0; x < 20; x++)
{
farr[(rand() & 1)](1);
}
}
or everything together
int fun1(int a){
return printf("%s\n",__FUNCTION__);
}
int fun2(int a){
return printf("%s\n",__FUNCTION__);
}
int fun3(int a){
return printf("%s\n",__FUNCTION__);
}
int fun4(int a){
return printf("%s\n",__FUNCTION__);
}
typedef int func(int);
typedef int (*fa[2])(int);
int main()
{
func *farr[2];
func **fapp = malloc(2*sizeof(*fapp));
fa *fap = malloc(2 * sizeof(*fap));
farr[0] = fun1;
farr[1] = fun2;
fapp[0] = fun1;
fapp[1] = fun2;
fap[0][0] = fun1;
fap[0][1] = fun2;
fap[1][0] = fun3;
fap[1][1] = fun4;
for(int x = 0; x < 20; x++)
{
farr[(rand() & 1)](1);
}
printf("------------------------------\n");
for(int x = 0; x < 20; x++)
{
int x = rand() % 4;
fap[x / 2][x & 1](1);
}
printf("------------------------------\n");
for(int x = 0; x < 20; x++)
{
fapp[rand() & 1](1);
}
}
https://godbolt.org/z/OSFGSp
Related
I am wondering that unlike the double pointers (int**) , can we have double function pointer?
I mean the function pointer pointing to the address of the another function pointer ?
I want something like
int add(int A , int B){
return A+B;
}
int main(void){
int (*funcpointerToAdd)(int,int) = add; // single function pointer pointing to the function add
printf("%d \n",funcpointerToAdd(2,3));
int (**doubleFuncPointerToAdd)(int,int) = &funcpointerToAdd;
printf("%d \n",doubleFuncPointerToAdd(2,3));
return 0;
}
but this gives me an error called object ‘doubleFuncPointerToAdd’ is not a function or function pointer
is this possible to do this thing anyway ?
You can use pointers to pointers to functions, but you have to deference them once first:
int add(int A , int B){
return A+B;
}
int main(void){
int (*funcpointerToAdd)(int,int) = &add;
//By the way, it is a POINTER to a function, so you need to add the ampersand
//to get its location in memory. In c++ it is implied for functions, but
//you should still use it.
printf("%d \n",funcpointerToAdd(2,3));
int (**doubleFuncPointerToAdd)(int,int) = &funcpointerToAdd;
printf("%d \n",(*doubleFuncPointerToAdd)(2,3));
//You need to dereference the double pointer,
//to turn it into a normal pointer, which you can then call
return 0;
}
This is also true for other types:
struct whatever {
int a;
};
int main() {
whatever s;
s.a = 15;
printf("%d\n",s.a);
whatever* p1 = &s;
printf("%d\n",p1->a); //OK
//x->y is just a shortcut for (*x).y
whatever** p2 = &p1;
printf("%d\n",p2->a); //ERROR, trying to get value (*p2).a,
//which is a double pointer, so it's equivalent to p1.a
printf("%d\n",(*p2)->a); //OK
}
He folks,
i got a problem and a question.
Hopefully u can help and explain me.
first of all i have 2 stucts:
typedef struct {
double x;
double y;
} A;
typedef struct {
unsigned int count;
A(*stack)[];
}B;
this struct B i declare in main() and passing a Pointer of B to a function this will initializ
main(){
B x;
function rr(&x);
}
void rr(B* test) {
test->stack= malloc((4) * sizeof(A)); //4Elements
for (unsigned int i = 0; i < 4; i++) {
(test->stack+ i)->x= 89;
}
}
on this line
(test->stack+ i)->x= 89;
compiler says incomplete Type
i know why it is incomplete cause in struct B their is no dimension.
but array should initialize in function rr
Maybe u understand what i mean and how to solve my problem.
function rr i am not allowed to change.
Greetings
EDIT 1
Thank you for all answers
mabey i schould clearify my problem
typedef struct {
unsigned int count;
A(*stack)[]; // here i want a pointer to an array of A's
}B;
//over main it is declared
void rr(B*);
main(){
B x;
function rr(&x);
}
// this func is not allowed to change
void rr(B* test) {
test->stack= malloc((4) * sizeof(A)); //4Elements
for (unsigned int i = 0; i < 4; i++) {
(test->stack+ i)->x= 89; // error cause incomplete type but i
//have to use this line
}
}
Hope now it is easier to i understand what i want
This declaration:
A(*stack)[];
Says that stack is a pointer to an array of A of unknown size. That is an incomplete type which means it can't be used directly.
It seems like what you actually want is not a pointer to an array, but a pointer to the first member of a dynamic array of A. So declare the member as a pointer:
A *stack;
In the expression:
(test->stack+ i)->x= 89;
before accessing an array via a pointer to an array you must dereference it.
Try:
(*test->stack)[i].x= 89;
You do not know how to use flexible array members.
Simply:
typedef struct {
double x;
double y;
} A;
typedef struct {
size_t count;
A stack[];
}B;
B *createStack(size_t size)
{
B *s = malloc(sizeof(*s) + size * sizeof( s -> stack[0]));
return s;
}
void rr(B* test) {
for (unsigned int i = 0; i < 4; i++) {
(test->stack+ i)->x= 89;
}
}
int main(void)
{
B *stack = createStack(4);
rr(stack);
free(stack);
}
You need only one allocation to mallloc/realloc or free the structure. The array will decay into pointer for your assignment in rr function.
Say I have a function called array_push in c.
void array_push(int *array_pointer, int array_length, int val) {
int i;
int *temp_array = malloc(sizeof(int) * (array_length + 1));
for (i = 0; i < array_length; i++) {
temp_array[i] = *array_pointer;
array_pointer++;
}
temp_array[array_length] = val;
*array_pointer = temp_array;
}
How can I update the pointer *array_pointer so that it points to temp_array and other parts of my program can use the new array? Allowing me to do something like
int t[2] = {0,2};
array_push(t, 2);
/* t should now contain {0,2,3} */
You need to turn array_pointer into a pointer-to-pointer:
void array_push(int **array_pointer, int array_length, int val) {
(note the extra asterisk).
Also, you'll need to change the call site so that t is a pointer, not an array (you can't make an array point someplace else). Finally, to make the caller aware of the new size of the array, array_length also needs to be passed by pointer.
Thus, the overall structure of your code could be something like:
void array_push(int **array_pointer, int *array_length, int val) {
int *temp_array = malloc(sizeof(int) * (*array_length + 1));
memcpy(temp_array, *array_pointer, sizeof(int) * *array_length);
temp_array[(*array_length)++] = val;
free(*array_pointer);
*array_pointer = temp_array;
}
int main() {
int n = ...;
int* t = malloc(sizeof(int) * n);
/* ... */
array_push(&t, &n, 2);
/* ... */
free(t);
}
Note how I've allocated t on the heap, and have freed *array_pointer inside array_push(). With this in mind, much of the array_push()'s logic can be simplified by using realloc():
void array_push(int **array_pointer, int *array_length, int val) {
*array_pointer = realloc(*array_pointer, sizeof(int) * (*array_length + 1));
(*array_pointer)[(*array_length)++] = val;
}
There are two problems here: You seem confused about pass-by-value, but the more significant problem is that you seem confused about pointers. int *array_pointer array_pointer points to an int, not an array. It may be that it points to the first int in an array. On an unrelated note, a "pointer to an int array" looks like: int (*array_pointer)[array_length].
Back to the point: int *array_pointer array_pointer points to an int. In *array_pointer = temp_array;, the expression *array_pointer gives you the object pointed to, which can store an int. temp_array isn't an int value, though.
I can see that you're attempting to work around the issue that changes made to array_pointer aren't visible to the caller, due to the semantics of pass-by-value. Hence, you need to change array_pointer so that it points to an int * that the caller supplies, so that you're modifying the caller's int *, or use the return type to return the new pointer. As it turns out, both of these options solve both of your problems.
PROBLEM 1:
If you want to create or modify an *int array inside of a function, then you need to pass a "pointer to a pointer":
// WRONG:
void array_push(int *array_pointer, int array_length, int val) {
...
int *temp_array = malloc(sizeof(int) * (array_length + 1));
...
*array_pointer = temp_array;
Instead:
// BETTER:
void array_push(int **array_pointer, int array_length, int val) {
...
int *temp_array = malloc(sizeof(int) * (array_length + 1));
...
*array_pointer = temp_array;
Or:
// BETTER YET:
int * array_push(int array_length, int val) {
...
int *temp_array = malloc(sizeof(int) * (array_length + 1));
...
return temp_array;
PROBLEM 2:
If you want to declare a static array like this int t[2] = {0,2};, then you can't arbitrarily change it's size. Here's a good description of "arrays vs pointers":
http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?answer=1069897882&id=1073086407
One of the first things a new student learns when studying C and C++
is that pointers and arrays are equivalent. This couldn't be further
from the truth...
I want to make a function pointer array and be able to call them in a for-loop. How can I achieve this? I have tried:
void (**a) (int);
a[0] = &my_func1;
a[1] = &my_func2;
a[2] = &my_func3;
for ( i = 0; i < 3; i++){
a[0]();
(*a[0])(); // Neither does work
}
But I am missing some syntax I guess:
error: too few arguments to function ‘*(a + (long unsigned int)((long unsigned int)i * 8ul))’
The function you declare is expected to take an int as a parameter:
a[0](1);
Also note that you declare a pointer to pointer for the functions, but you don't allocate any memory for them (I assume this is only in the example) Otherwise it should probably be:
void (*a[3]) (int);
You are declaring that a is a pointer to a pointer to (or an array of pointers to) a function that takes an int as a parameter - so you need to pass an int when you call the functions, e.g. a[0](42);.
I guess the below code is what you need.
typedef void * func_pointer(int);
func_pointer fparr[10];
for(int i = 0; i<10; i++)
{
fparr[i](arg); //pass the integer argument here
}
1) Where have you allocated or defined array to store function addresses?
2) in loop you are always calling (*a[0])();,There should be loop counter
You forgot to give an argument to your function.
void (**a) (int); // here it takes an int argument
a[0] = &my_func1;
a[1] = &my_func2;
a[2] = &my_func3;
for ( i = 0; i < 3; i++){
a[0](); // here you do not give an argument
}
But be careful, you do not allocate memory to your a array, and it fails with a nice segmentation fault error.
void my_func1(int i) {
;
}
void my_func2(int i) {
;
}
void my_func3(int i) {
;
}
int main() {
void (**a) (int);
a = malloc(3*sizeof(void*)); // allocate array !
a[0] = &my_func1;
a[1] = &my_func2;
a[2] = &my_func3;
for (int i = 0; i < 3; i++){
a[i](1); // respect your own function signature
}
free(a); // it's always a good habit to free the memory you take
return 0;
}
You can typedef void (*pfun)(int); and then pfun a[3]; is the array you want.
The following code may work for you:
typedef void (*pfun)(int);
int main() {
pfun a[3];
a[0] = myfunc1; // or &myfunc1 whatever you like
a[1] = myfunc2;
a[2] = myfunc3;
}
You can define your function-array with the needed size and initialize it with your functions like:
void my_func1(int x){}
void my_func2(int x){}
void my_func3(int x){}
void (*a[])(int)={my_func1,my_func2,my_func3};
int i;
for(i=0;i<sizeof a/sizeof*a;++i)
a[i](i);
The address-operator '&' before any function-name is redundant.
I have the following code:
int takeEven(int *nums, int numelements, int *newlist) {
newlist = malloc(numelements * sizeof *newlist);
int i, found = 0;
for(i = 0; i < numelements; ++i, nums++) {
if (!(*nums % 2)) {
*(newlist++) = *nums;
found++;
}
}
newlist -= found;
printf("First number found %d\n", *newlist); // <= works correctly
return found;
}
int main()
{
int nums[] = {1,2,3,4,5};
int *evenNums;
int i;
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), evenNums);
for (i = 0; i < n; ++i) {
printf("%d\n", *(evenNums++));
}
return 0;
}
The output of the above code:
-1
2088999640
2088857728
If I try printing the first element of the newlist pointer before returning the function (printf("First number found %d\n", *newlist);), it works as intended, but why is it that when I try to access the pointer from outside of the function I get those values from seemingly unmalloced addresses?
You are passing the newList pointer by value, so it will not be modified by your function. You should do instead.
int takeEven(int *nums, int numelements, int **newlist) {
*newlist = malloc(numelements * sizeof *newlist);
...
}
...
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);
You need to pass in a pointer to pointer, i.e. int **newlist. Specifically, newlist is being passed into your function by value, so the newlist in main and inside your function are two completely different variables.
There is also a bug in your test for even numbers:
#include <stdio.h>
#include <stdlib.h>
int takeEven(int *nums, int numelements, int **newlist) {
int *list = malloc(numelements * sizeof **newlist);
*newlist = list; // this modifies the value of newlist in main
int i, found = 0;
for(i = 0; i < numelements; ++i, nums++) {
if ((*nums % 2) == 0) {
*(list++) = *nums;
found++;
}
}
list -= found;
printf("First number found %d\n", *list); // <= works correctly
return found;
}
int main()
{
int nums[] = {1,2,3,4,5};
int *evenNums;
int i;
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);
for (i = 0; i < n; ++i) {
printf("%d\n", *(evenNums++));
}
return 0;
}
You can also take a look at this question from the C-FAQ which deals with your problem also:
Q: I have a function which accepts, and is supposed to initialize, a pointer:
void f(int *ip)
{
static int dummy = 5;
ip = &dummy;
}
But when I call it like this:
int *ip;
f(ip);
the pointer in the caller remains unchanged.
A: Are you sure the function initialized what you thought it did? Remember that arguments in C are passed by value. In the code above, the called function alters only the passed copy of the pointer. To make it work as you expect, one fix is to pass the address of the pointer (the function ends up accepting a pointer-to-a-pointer; in this case, we're essentially simulating pass by reference):
void f(ipp)
int **ipp;
{
static int dummy = 5;
*ipp = &dummy;
}
...
int *ip;
f(&ip);
Another solution is to have the function return the pointer:
int *f()
{
static int dummy = 5;
return &dummy;
}
...
int *ip = f();
See also questions 4.9 and 4.11.
The newlist you have at the end of the function is not the same as you have when calling the function.
You are passing a copy of a pointer, then malloc changes that pointer(internal to the function) to point to allocated memory, but the outside one is still unmodified.
You need to use a pointer to pointer as a parameter so that you can set where the ourtside one points by double indirection.
int use_pointed_memory(char **pointer){
*pointer = malloc();
}
char *myptr;
use_pointed_memory(&myptr);
So effectively you are giving the function the place where you store the address of what you want and asking the function to store there a valid memory pointer.
You're passing a pointer by value here:
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), evenNums);
Which means that a copy of the pointer is made within that function. You then overwrite that copy:
newlist = malloc(numelements * sizeof *newlist);
Since it is but a copy, the caller won't see the result of your assignment. What you seemingly want here is to pass a pointer by reference - for that, you need a pointer to pointer:
int takeEven(int *nums, int numelements, int **newlist) {
*newlist = malloc(numelements * sizeof **newlist); // apply * to newlist
...
}
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);
And don't forget to free:
free(evenNums);
In C, everything is passed by value. So you are passing a copy of evenNums to the function. Whatever you modify it inside the function doesn't get reflected outside. You need to int** as the third parameter.