Let's see what the C Standard says about using array designators in expressions (6.3.2.1 Lvalues, arrays, and function designators)
3 Except when it is the operand of the sizeof operator or the unary &
operator, or is a string literal used to initialize an array, an
expression that has type ‘‘array of type’’ is converted to an
expression with type ‘‘pointer to type’’ that points to the initial
element of the array object and is not an lvalue. If the array
object has register storage class, the behavior is undefined.
You declared a two-dimensional array with static storage duration within the function fivearray
static int arr[5][5];
and are using it as an expression in the return statement
return arr;
So the array arr
is implicitly converted in this return statement to pointer to the array element type.
What is the element type of the array? It is the type int[5]
. So the pointer to an object of this type will have the type int ( * )[5]
.
But you specified the return type as int **
.
int** fivearray(){
However there is no implicit conversion between the pointer types int ( * )[5]
and int **
.
So the return type of the function is incorrect. You have to write
int ( *fivearray( void ) )[5]{
static int arr[5][5];
// ...
return arr;
}
Now let's consider the for loop within the function
for(short i = 0; i<25; ++i){
**(arr+i) = i;
What is interesting in this loop for us is the expression **( arr + i )
.
As it was already noted the array used in this expression is converted to pointer of the type int ( * )[5]
.
Dereferencing the pointer expression *( arr + i )
you will get i-th "row" of the array that is its i-th element of the type int[5]
. So you may rewrite the expression like
arr[i]
It is a one-dimensional array. Applying the second dereferencing operator to this expression
*( arr[i] )
that is the same as **( arr + i )
you will get the first element of the array because again the array arr[i]
is implicitly converted to pointer to its first element.
Thus this statement
**(arr+i) = i;
sets the first element of each "row" of the two-dimensional array to the value i
.
But the array has only 5 rows. On the other hand, the variable i
is being changed from 0
to 25
. So this statement
**(arr+i) = i;
tries to access memory beyond the array when the variable i
is greater than 4
.
As a result the loop invokes undefined behavior.
To make it visually clear consider the following demonstrative program. I changed the first dimension of the array to 25 to guarantee that there will not be an access beyond the array.
#include <stdio.h>
int main(void)
{
int arr[35][5] = { 0 };
for ( size_t i = 0; i < 25; i++ )
{
**( arr + i ) = i;
}
for ( size_t i = 0; i < 25; i++ )
{
for ( size_t j = 0; j < 5; j++ )
{
printf( "%d\t", arr[i][j] );
}
putchar( '\n' );
}
return 0;
}
The program output is
0 0 0 0 0
1 0 0 0 0
2 0 0 0 0
3 0 0 0 0
4 0 0 0 0
5 0 0 0 0
6 0 0 0 0
7 0 0 0 0
8 0 0 0 0
9 0 0 0 0
10 0 0 0 0
11 0 0 0 0
12 0 0 0 0
13 0 0 0 0
14 0 0 0 0
15 0 0 0 0
16 0 0 0 0
17 0 0 0 0
18 0 0 0 0
19 0 0 0 0
20 0 0 0 0
21 0 0 0 0
22 0 0 0 0
23 0 0 0 0
24 0 0 0 0
As you can see this expression **( arr + i ) = i;
changed only the first element of each "row" of the array.
What you need is to use two loops like
for(short i = 0; i < 5; ++i ){
for ( short j = 0 j < 5; j++ ){
arr[i][j] = 5 * i + j;
printf( "%d\t", arr[i][j] );
}
}
Or if to use only one for loop then you need to write
for(short i = 0; i < 25; ++i){
arr[i / 5][i % 5] = i;
printf( "%d\t", arr[i / 5][i % 5] );
}
Thus the function will look like
int ( *fivearray( void ) )[5] {
static int arr[5][5];
for( short i = 0; i < 25; ++i){
arr[i / 5][i % 5] = i;
printf( "%d\t", arr[i / 5][i % 5]);
}
return arr;
}
At last in main you should write
int ( *array )[5] = fivearray();
Pay attention to that it is not a good idea to use magic number like 5 throughout the program.
You could introduce a named constant for the magic number 5 like for example
enum { N = 5 };
int ( *fivearray( void ) )[N] {
static int arr[N][N];
for( short i = 0; i < N * N; ++i){
arr[i / N][i % N] = i;
printf( "%d\t", arr[i / N][i % N]);
}
return arr;
}
int main( void )
{
int ( *array )[N] = fivearray();
}