How C++ understands Array as pointers point of view? - c++

I wrote the piece of code below but when I tried to return some two-dimensional array, it throws the following error.
int (* function (int input[2][2]) ) [2][2]{
return input;
}
from trial and error, I understand that when I change the function declaration to int (* function (args) ) [2] {...} it works like a charm, but why??? I don't understand. How C++ actually sees arrays? How these return declarations int (* function () )[n][m] actually works? What happens when I add another * to function declaration int *(* function () )[n][m] ??
My source for finding the solution to this problem was this but I just copied some code and understood almost 0% of it.
It'll be nice if someone could explain to me how these work, and it would mean a world to me if you can suggest a good reading source for understanding these somewhat advanced notions in C++.

In this function declaration
int (* function (int input[2][2]) ) [2][2];
the argument of the array type is implicitly adjusted by the compiler to pointer to the array element type. That is for example these function declarations
int (* function (int input[2][2]) ) [2][2];
int (* function (int input[100][2]) ) [2][2];
int (* function (int input[][2]) ) [2][2];
declares the same one function that is equivalent to
int (* function (int ( *input )[2]) ) [2][2];
So within the function the variable input has the pointer type int ( * )[2]. This pointer you are returning from the function
return input;
So the function return type also must be int ( * )[2]. That means that the function must be declared like
int (* function (int input[2][2]) ) [2];
You could declare the parameter as having a referenced type. In this case you may return reference to the array.
int ( & function (int ( &input )[2][2]) )[2] [2];
Array types may not be used as the return type of function.
As for this declaration
int *(* function () )[n][m];
where n and m shall be constant expressions then the function returns pointer of the type int * ( * )[n][m]. For example the function can use an array name declared within the function with the static storage duration something in a return statement like
static int * a[k][n][m];
//
return a;
So if you have an array as for example
T a[N1][N2][N3];
where T is some type and N1, N2, and N3 its sizes then this declaration you may rewrite like
T ( a[N1] )[N2][N3];
Used in expressions the array (with rare exceptions) is converted to pointer to its first element. To declare such a pointer substitute the record in the parentheses to pointer like
T ( *p )[N2][N3] = a;

Related

how to read this declaration int (*(*f2)(int n))[3];

I got this declaration from https://en.cppreference.com/w/cpp/language/scope, but don't know how to parse this declaration even there is a comment below.
my questions is
how to parse the declaration statement (I see it as a function pointer to a function protocol like "int[3] foo(int n)" or "int foo(int n)[3] --- they are illegal in C++ )? Then, how can I construct a concrete function which can be assigned to this function pointer? Thanks.
const int n = 3;
int (*(*f2)(int n))[n]; // OK: the scope of the function parameter 'n'
// ends at the end of its function declarator
// in the array declarator, global n is in scope
// (this declares a pointer to function returning a pointer to an array of 3 int
It's a pointer to a function taking an int and returning a pointer to an int array of size three.
All the comment is saying is that there are two n identifiers in play here. The [n] (in array declarator) is using the const int 3, not the parameter to the function (which is in the function declarator).
Starting in the middle, with each segment being included in the subsequent bullet point as ...:
f2 is a pointer, (*f2).
It's a pointer to a function taking an integer, ...(int).
It returns a pointer to an int array of size three, int (*...)[3].
You can form a concrete function for it as per the following complete program, which output the first element, 42:
#include <iostream>
const int n = 3;
int (*(*f2)(int n))[n];
int (*g2(int))[n] {
static int x[::n] = { 42 }; // Use outer n, not the parameter.
return &x; // since C++ has no VLAs. This
// means parameter is not actually
// needed in this test case, though
// it may be in more complicated
// tests.
}
int main() {
f2 = &g2; // Assign concrete function to pointer.
auto y = f2(3); // Call via pointer, get array.
std::cout << *(y[0]) << '\n'; // Deref first element to get 42.
}
Having said that, I would be rather curious if one of my colleagues submitting something like that for a code review, at least without a large comment explaining it. Although seasoned developers may be able to work it out, those less experienced may have trouble.
And, in fact, even seasoned developers shouldn't have to work it out, especially given it took me a few minutes.
C++ has a very expressive type system which can easily build something like this up in parts, so you don't have to experience migraines trying to work it out. For something like this, I'd be using std::vector (or std::array) unless there was a compelling case for the added complexity caused by more basic types.
You can create a type for pointer to an array of 3 int
typedef int (*array_with_size_n)[n];
and then use it as return type
const int n = 3;
int (*(*f2)(int n))[n];
int arr[n];
array_with_size_n func(int n)
{
return &arr;
}
int main()
{
f2 = &func;
return 0;
}

C++ pointers objects difference

Can somebody explain me the difference between the following?
Those two
float *pointer[10];
float *(pointer[10]);
and those two
int(*pointer_function)();
int *pointer_function();
These two declarations
float *pointer[10];
float *(pointer[10]);
are equivalent. You can write even the following way
float *( ( pointer )[10] );
That is it is a declaration of an array of 10 pointers to float.
These declarations
int(*pointer_function)();
int *pointer_function();
are different. The first one declares a pointer to a function of type int(). The second one declares a function (not a pointer to a function) with type int *().
Here is a demonstrative program
#include <iostream>
int * pointer_function() // #1
{
static int x = 1'000'000;
return &x;
};
int f1() // #2
{
return 2'000'000;
}
int main()
{
std::cout << *pointer_function() /* calling #1 */<< '\n';
int( *pointer_function )() = f1;
std::cout << pointer_function() /* calling #2 */ << '\n';
return 0;
}
Its output is
1000000
2000000
To make more obvious the difference between the declarations you can rewrite the second declaration (that is the declaration of function) the following way
int * ( pointer_function )();
Compare it with the pointer to function declaration
int ( *pointer_function )();
Take into account that a declarator may be enclosed in parentheses.
Always keep in mind the place of Parentheses. Parentheses do not alter the type of the object, but they can alter the binding of complex declarators.
From above code snippet:
float *pointer[10];// Array of 10 pointer to float
float *(pointer[10]); //bracket around array of 10 pointer to float, So same as above
int(*pointer_function)(); // function pointer to achieve callbacks
int * pointer_function(); // function to integer pointer

How to read the function pointer?

How to interpret the following c++ declaration?
int (*(*x[2])())[3];
This is from the example present at Type-cppreference.
The interpretation of the sample declaration in the question is present in the Type-cppreference page linked.
int (*(*x[2])())[3]; // declaration of an array of 2 pointers to functions
// returning pointer to array of 3 int
So the actual question is not about that case in particular; but about how any C++ declaration shall be read.
You can infer all those details starting at the declared name x and moving clockwise respecting parenthesis. You will get to the description above:
x is a an array of dimension 2 of pointers to functions that return a pointer to an array of dimension 3 of ints.
Better explained here as the Clockwise/Spiral Rule: http://c-faq.com/decl/spiral.anderson.html
It is an array of two pointers to functions that return pointer to array of type int[3] and do not have parameters.
Here is a demonstrative program
int ( *f() )[3] { return new int[2][3]; }
int ( *g() )[3] { return new int[4][3]; }
int main()
{
int (*(*x[2])())[3] = { f, g };
for ( auto func : x ) delete []func();
return 0;
}

How do you make a function "size-aware" of its parameters?

From here: https://stackoverflow.com/a/3473454/499125
int ( &fillarr( int (&arr)[5] ) )[5] { // no decay; argument must be size 5
return arr;
}
The definition above can force the compiler to become size-aware of its parameters. This statement seems complex to me. Can someone give an anatomy of this statement or explain how does the statement achieves the size-awareness?
Can this be extended to handle multiple parameters?
It all boils down to being able to read the declaration. A simpler way of writing exactly the same would be:
typedef int int5[5]; // create a typedef
int5& fillarr( int5& ) {
}
As of the exact way of reading the original declaration, just break it into pieces:
int (&fillarr( int (&arr)[5] ))[ 5 ];
^^^^^^^^^^^^^ // A: reference to array of 5 int
^^^^^^ ^^^^^^ // B: reference to array of 5 int
^^^^^^^^ ^ // C: function taking A and returning B
You can split understanding this in two parts, 1) the return value and 2) the parameter type:
int ( &fillarr() )[5] {
static int arr[5];
return arr;
}
We can have a look at the type: int (&fillarr())[5]. To understand this, unfortunately the old C rule: "Declaration is like usage in expressions" doesn't work with references, so let's have a look at a similar declaration instead:
int (*fillarr())[5];
This is a function that returns a pointer instead of a reference to an array of size 5. How do I figure? Well, assume we do have a function f that returns a pointer to an array of ints, how would we access the fifth element? Let's see, we first have to call the function: f(). Then we have to dereference the result *f() and then access the fifth element (which doesn't exist, but ignore that) (*f())[5] which is an int. This is exactly the declaration syntax:
int x;
int (*f())[5];
x = (*f())[5];
// ^^^-------- call f -> yields pointer to array of 5 ints
// ^----------- dereferene the result of f -> yields array of 5 ints
// ^^^---- access the fifth element
Now you only substitute the * for an & because you're returning a reference in your example.
The parameter syntax works analogously.

How define an array of function pointers in C

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);
}