int (*x(int))[5] says x is a function that takes an int argument, and returns a pointer to an integer array of 5 elements.
I can also use typedef to simplify x:
typedef int Array[5];
typedef Array *Array_ptr;
typedef Array_ptr Array_ptr_fn(int);
My question is, how do I use this type Array_ptr_fn?
// Define some_x to have type Array_ptr_fn,
Array_ptr_fn some_x;
// But then how do I use some_x since function cannot return array.
The first thing to note is that x is not a function pointer, but an actual function declaration. It's not a variable. A pointer to x would have the type int (*(*ptr_to_x)(int))[5].
The second thing to note is that the return value of x is neither int[5], nor int[], nor int*, but int (*)[5]. That is, you need to write (*retval)[0] to get to an actual int value.
With that in mind, it's not that hard to write a proof of concept that uses these types:
#include <stdio.h>
int arr[5] = { 11, 22, 33, 44, 55 };
int (*ptr)[5] = &arr;
int (*x(int ignored))[5]
{
return ptr;
}
int main(void)
{
int (*(*ptr_to_x)(int))[5] = &x;
int (*i)[5] = ptr_to_x(123);
printf("%d\n", (*i)[2]);
return 0;
}
Array_ptr_fn some_x; /* ERROR */
You cannot use the type Array_ptr_fn to define a variable... but you can use a pointer to that type to store a function reference (with that interface) to be called in the future, as in:
int (*f1(int))[5]; /* implemented elsewhere */
Array_ptr_fn *some_function = f1;
int (*my_array)[5] = f1(27);
/* or equivalently */
int (*my_second_array)[5] = some_function(27);
Related
I have this code:
#include <stdio.h>
int main(void) {
int b[] = {1,2,3};
int *a = b; //works
int c = 1;
int *d = c; //doesn't work
}
Why is it that it works to initialize the pointer with an array but not an int?
int *d = c; it does work. It is simply converting the integer number held in c into a pointer. The compiler will issue the warning (unless you cast explicitly).
You can use it, for example, to read from a particular address of memory.
unsigned read_from_memory_address(unsigned address)
{
unsigned *x = (unsigned *)address;
return *x;
}
Of course, how this function will behave (or what type address should have) is implementation defined.
Pointers keep references to objects. If you want pointer to reference an integer variable you need to supply the reference (address) of this variable.
int *x = &c;
Arrays in expressions decay to pointer to first element of the array. That is why you do not need to use & in front of the array (you can, but the pointer will have a different type - in this case pointer to array).
int array[3];
int *x = array; //decays to pointer to first element
int (*y)[3] = &array; //pointer to array of 3 `int` elements
From what I know, local variables (not declared using the static keyword) within functions only exist for as long as the function is on the stack frame and when control returns to the caller all local variables are destroyed. This would explain why it is not possible to return a locally defined array from a function. Trying to dereference such an array returned would give us garbage values at best or a segfault at worst. Shouldn't this also be true for structures? That is, if we are returning a structure from a function, shouldn't trying to access its members also give us garbage values or a segfault?
I have the following two files for demonstrating. The first one is for arrays:
/* return_local_vs_malloc_array.c */
#include <stdio.h>
#include <stdlib.h>
#define LEN 10
#define VAL 100
int *return_local() {
int arr[LEN] = {VAL};
return arr;
}
int *return_mallocated() {
int *arr = (int *)malloc(sizeof(int)*LEN);
for (int i = 0; i < LEN; i++)
arr[i] = VAL;
return arr;
}
void display(int *arr) {
for (int i = 0; i < LEN; i++) {
printf("%d ", arr[i]);
}
putchar('\n');
}
int main(void) {
int *x = return_local();
fputs("local: ", stdout); display(x);
int *y = return_mallocated();
fputs("malloc: ", stdout); display(y);
free(y);
return 0;
}
and the other one is for structs:
/* return_local_vs_malloc_struct.c */
#include <stdio.h>
#include <stdlib.h>
struct foobar {
int foo;
int bar;
};
struct foobar return_local(int foo, int bar) {
struct foobar f;
f.foo = foo;
f.bar = bar;
return f;
}
struct foobar *return_mallocated(int foo, int bar) {
struct foobar *f = (struct foobar *)malloc(sizeof(struct foobar));
f->foo = foo;
f->bar = bar;
return f;
}
int main(void) {
struct foobar x = return_local(10, 20);
printf("local: x = {foo: %d, bar: %d}\n", x.foo, x.bar);
struct foobar *y = return_mallocated(10, 20);
printf("malloc: y = {foo: %d, bar: %d}\n", y->foo, y->bar);
free(y);
return 0;
}
When I run this I get:
$ tcc -run ./return_local_vs_malloc_array.c
local: x = -1519296757 32767 0 0 -849137592 32767 -849137536 7 -849137608 32767
malloc: y = 100 100 100 100 100 100 100 100 100 100
~/
$ tcc -run ./return_local_vs_malloc_struct.c
local: x = {foo: 10, bar: 20}
malloc: y = {foo: 10, bar: 20}
As you can see, the locally allocated structure persists even when control has returned from the function in which it was declared. From what I know, this is not supposed to happen and the only way one can make a local variable persist beyond the lifetime of the called function is by using the static qualifier. But maybe I am wrong?
When a function returns a struct (or any other type of variable) by value, then a copy of that variable or structure is made, and that copy is returned to the caller. So, even though the 'original' has ceased to exist when the function ends, the copy is still valid.
However, when a function returns an array, what is actually returned is the address of the first element of that array – see What is array to pointer decay? So, in such cases, when the function has completed, the local array no longer 'exists' and the address returned becomes invalid.
You can 'emulate' this behaviour for a struct by redefining your function to return the address of the local variable, like so:
struct foobar {
int foo;
int bar;
};
// Note: BAD function, for example purpose only. DO NOT USE IT!
struct foobar* return_local(int foo, int bar) // Return a pointer-to-struct
{
struct foobar f;
f.foo = foo;
f.bar = bar;
return &f; // Any caller that attempts to use this returned pointer will
// exhibit Undefined Behaviour, as the 'f' struct will be gone!
}
You can not return an array because arrays can not be used as an initializers of other arrays. That is you can not write for example
int arr1[LEN] = {VAL};
int arr2 = arr1;
So when you use an array designator as an expression of a return statement it is implicitly converted to pointer to its first element. That is it is the pointer that is returned not the array itself. And the pointer becomes invalid because the array with the automatic storage duration pointed to by the pointer will not be alive after exiting the function.
On the other hand, one object of a structure type can be used as an initializer of another object of the structure type. For example
struct foobar f1 = { .foo = 10, .bar = 20 };
struct forbar f2 = f1;
So when an object of a structure type is returned from a function then there is created a copy of the returned object that can be assigned to an object of the structure type in the caller of the function.
I've a little question.
I'm trying to define an array of function pointers dynamically with calloc.
But I don't know how to write the syntax.
Thanks a lot.
The type of a function pointer is just like the function declaration, but with "(*)" in place of the function name. So a pointer to:
int foo( int )
would be:
int (*)( int )
In order to name an instance of this type, put the name inside (*), after the star, so:
int (*foo_ptr)( int )
declares a variable called foo_ptr that points to a function of this type.
Arrays follow the normal C syntax of putting the brackets near the variable's identifier, so:
int (*foo_ptr_array[2])( int )
declares a variable called foo_ptr_array which is an array of 2 function pointers.
The syntax can get pretty messy, so it's often easier to make a typedef to the function pointer and then declare an array of those instead:
typedef int (*foo_ptr_t)( int );
foo_ptr_t foo_ptr_array[2];
In either sample you can do things like:
int f1( int );
int f2( int );
foo_ptr_array[0] = f1;
foo_ptr_array[1] = f2;
foo_ptr_array[0]( 1 );
Finally, you can dynamically allocate an array with either of:
int (**a1)( int ) = calloc( 2, sizeof( int (*)( int ) ) );
foo_ptr_t * a2 = calloc( 2, sizeof( foo_ptr_t ) );
Notice the extra * in the first line to declare a1 as a pointer to the function pointer.
I put a small example here that may help you
typedef void (*fp)(int); //Declares a type of a void function that accepts an int
void test(int i)
{
printf("%d", i);
}
int _tmain(int argc, _TCHAR* argv[])
{
fp function_array[10]; //declares the array
function_array[0] = test; //assings a function that implements that signature in the first position
function_array[0](10); //call the cuntion passing 10
}
You'd declare an array of function pointers as
T (*afp[N])();
for some type T. Since you're dynamically allocating the array, you'd do something like
T (**pfp)() = calloc(num_elements, sizeof *pfp);
or
T (**pfp)() = malloc(num_elements * sizeof *pfp);
You'd then call each function as
T x = (*pfp[i])();
or
T x = pfp[i](); // pfp[i] is implicitly dereferenced
If you want to be unorthodox, you can declare a pointer to an array of pointers to functions, and then allocate that as follows:
T (*(*pafp)[N])() = malloc(sizeof *pafp);
although you would have to deference the array pointer when making the call:
x = (*(*pafp)[i])();
typedef R (*fptr)(A1, A2... An);
where R is the return type, A1, A2... An are the argument types.
fptr* arr = calloc(num_of_elements,sizeof(fptr));
Assuming all your functions are of type void ()(void), something like this
typedef void (*fxptr)(void);
fxptr *ptr; // pointer to function pointer
ptr = malloc(100 * sizeof *ptr);
if (ptr) {
ptr[0] = fx0;
ptr[1] = fx1;
/* ... */
ptr[99] = fx100;
/* use "dynamic array" of function pointers */
free(ptr);
}
Here is the code which i got confused with.It would be great help if someone corrected this code?
int (*(x)())[2];
int main()
{
int (*(*y)())[2]=x;
x();
return 0;
}
int (*(x)())[2]
{
int **str;
str=(int*)malloc(sizeof(int)*2);
return str;
}
How to assign an array of pointers when returned by x?is using malloc only solution?
Thanks in advance
It's not entirely clear what you're trying to accomplish, so I'll cover more than one possibility.
First of all, a refresher on how to read and write complicated declarations in C:
Remember that () and [] have higher precedence than unary *, so *a[] is an array of pointers, while (*a)[] is a pointer to an array; similarly, *f() is a function returning a pointer, while (*f)() is a pointer to a function.
When you're trying to read a hairy declaration, start with the leftmost identifier and work your way out, remembering the rule above. Thus,
int (*(x)())[2];
reads as
x -- x
(x) -- x
(x)() -- is a function
*(x)() -- returning a pointer
(*(x)())[2] -- to a 2-element array
int (*(x)())[2] -- of int
In this case, the parens immediately surrounding x are redundant, and can be removed: int (*x())[2];.
Here's how such a function could be written and used:
int (*x())[2]
{
int (*arr)[2] = malloc(sizeof *arr); // alternately, you could simply write
return arr; // return malloc(sizeof (int [2]));
} // type of *arr == int [2]
int main(void)
{
int (*p)[2] = NULL; // alternately, you could write
... // int (*p)[2] = x();
p = x();
...
free(p);
}
Notice that the declarations of arr, p, and x() all look the same -- they all fit the pattern int (*_)[2];. THIS IS IMPORTANT. If you declare one thing as T (*p)[N] and another thing as T **q, then their types are different and may not be compatible. A pointer to an array of T is a different type than a pointer to a pointer to T.
If your goal is to create an array of pointers to functions returning int, then your types would look like int (*f[2])();, which reads as
f -- f
f[2] -- is a 2-element array
*f[2] -- of pointers
(*f[2])() -- to functions
int (*f[2])(); -- returning int
That would look something like the following:
int foo() {...}
int bar() {...}
int main(void)
{
int (*f[2])() = {foo, bar};
...
}
If you want a function that returns f, that's a little trickier. C functions cannot return array types; they can only return pointers to arrays, so your function declaration would be built up as
g -- g
g() -- is a function
*g() -- returning a pointer
(*g())[2] -- to a 2-element array
*(*g())[2] -- of pointers
(*(*g())[2])() -- to functions
int (*(*g())[2])() -- returning int
And such a beastie would be used something like this:
int foo() {...}
int bar() {...}
int (*(*g())[2])()
{
int (*(*f)[2])() = malloc(sizeof *f);
(*f)[0] = foo; // the type of the *expressions* foo and bar
(*f)[1] = bar; // is `int (*)()`, or pointer to function
return f; // returning int
}
int main(void)
{
int (*(*p)[2])();
int x, y;
...
p = g();
x = (*(*p)[0])();
y = (*(*p)[1])();
...
free(p);
...
}
Note that you can also build up hairy declarations from the outside in, using a substitution method. So,
int x(); -- x is a function returning int
int (*p)(); -- replace x with (*p) to get a pointer to a function
returning int
int (*a[2])(); -- replace p with a[2] to get an array of pointers
to functions returning int
int (*(*q)[2])(); -- replace a with (*q) to get a pointer to an array
of pointers to functions returning int
int (*(*g())[2])(); -- replace q with g() to get a function returning
a pointer to an array of pointers to functions
returning int.
Same result, different path. I prefer the first method, but either one should work.
Many people recommend using typedef to make things easier to read:
typedef int ifunc(); // ifunc is a synonym for "function returning int"
typedef ifunc *pifunc; // pifunc is a synonym for "pointer to function
// returning int
typedef pifunc farr[2]; // farr is a synonym for "2-element array of
// pointer to function returning int
typedef farr *pfarr; // pfarr is a synonym for "pointer to 2-element
// array of pointer to function returning int
pfarr g()
{
pfarr f = malloc(sizeof *f);
(*f)[0] = foo;
(*f)[1] = bar;
return f;
}
int main(void)
{
pfarr p = g();
int x, y;
x = (*(*p)[0])();
y = (*(*p)[1])();
...
}
Yes, the declarations are easier to read, but there's no connection between the declaration of pand the expression (*(*p)[1])(). You'd have to grovel back through all the typedefs to understand why that expression is written the way it is, building up a mental map for each typedef.
Yes, declarations like int (*(*g())[2])() are designed to make your eyes glaze over, hiding all that behind a typedef makes the situation worse IMO.
Don't understand what you want to do, maybe this can help
#include<stdio.h> // printf
#include<stdlib.h> // malloc free
int *x(); // forward declaration because used before definition
int main() {
int *y=x(); // y is a pointer on int
printf ("%d %d\n", y[0], y[1]);
free(y); // must call free because dynamic allocation
return 0;
}
int *x() {
int *res;
res=(int*)malloc(sizeof(int)*2); // dynamic allocation of an array of two int
// should check res != NULL
res[0]=10;
res[1]=20;
return res;
}
This following code will give you an array of pointers to functions, and standard procedures for assigning, passing of arrays applies.
#include <stdio.h>
#include <stdlib.h>
typedef int (*XFunc())();
XFunc *x[2]; /* array of XFunc pointers */
int f1()
{
printf("1\n");
return 1;
}
int f2()
{
printf("2\n");
return 2;
}
int main()
{
x[0] = (XFunc*)f1;
x[1] = (XFunc*)f2;
x[0]();
x[1]();
return 0;
}
The pointer x above will point to the first element in the (fixed) array, this pointer-value is the value that will be assigned to another variable.
I'm trying to do it this way:
int (*p)(void);
int *i;
...
p = (int *(void))i;
But it's causing syntax error:
error: cast specifies function type
What's wrong here?
You should respect error in this case. You must not convert a pointer to function to an int pointer or other way around. That might result in undefined behavior.
If you insist then, syntax should be:
p = (int (*)(void))i;
i is a pointer to an integer, and p is a function pointer returning and int and taking no arguments. They are not compatible/castable in any way, shape or form.
What the compiler says. int (*p)(void) is a function pointer declaration (pointer to a function which returns an int). int *i; is a scalar pointer declaration (pointer to an int). You can't cast one into the other.
Write
p = (int (*)(void))i;
Here's an example:
#include <stdio.h>
int f(){
printf("test\n");
return 0;
}
int main()
{
int (*p)(void);
int *i;
i = (int*)f;
p = (int (*)(void))i;
printf("i=%p\n", i);
printf("p=%p\n", p);
((int (*)(void))i)(); //here, it will call f()
return 0;
}
If you must do it ( and I am in no way saying that you should) then:
typedef int (*fp)(void);
int *i;
fp p;
...
p = (fp)((void*)i);
*i points to a simple integer, while *p is a pointer to a function with no arguments returning an integer. Thus, these two have completely different types, and because you said p shall point to a function returning an int, you can not tell it to point to an int.
However, you can try to wrap both in a union like the following:
union u {
int *i;
int (*p)(void);
};
int f(void){
return 5;
}
int main(int argc, char *argv[]) {
union u myU;
int a=6;
myU.i=&a;
myU.p=&f;
return 0;
}
Note that after assigning &f, you can simply call myU.p(). But if you leave out the assignment of &f and call myU.p() afterwards, it results in undefined behaviour (i.e. program crashes).
You don't. That is, unless you know better than the compiler that the pointer stored in your int * came from an int (*p)(void) in the first place. As others have said, that second type is a pointer to a function that takes no parameters and returns an int. The first type is a simple pointer to an integer (or more than one integer if treated as an array).