The presented program is totally incorrect. A variable length array may not have static storage duration/ According to the C Standard (6.7.6.2 Array declarators)
2 If an identifier is declared as having a variably modified type, it
shall be an ordinary identifier (as defined in 6.2.3), have no linkage,
and have either block scope or function prototype scope. If an
identifier is declared to be an object with static or thread storage
duration, it shall not have a variable length array type.
Moreover the pointer types double **
and double ( * )[cols]
(to which the array provided that it was declared correctly is converted in expressions) are not compatible. So the function is wrong.
double** example(int rows, int cols){
static double tr[rows][cols];
for(int i = 0; i < rows; i++)
for(int j = 0; j < cols; j++)
tr[j][i] = 0;
return tr;
}
Here is a demonstrative program that shows how to deal with variable length arrays.
#include <stdio.h>
void init( size_t rows, size_t cols, double a[rows][cols] )
// or
// void init( size_t rows, size_t cols, double a[][cols] )
// or
// void init( size_t rows, size_t cols, double ( *a )[cols] )
{
for ( size_t i = 0; i < rows; i++ )
{
for ( size_t j = 0; j < cols; j++ ) a[i][j] = 0.0;
}
}
void display( size_t rows, size_t cols, double a[rows][cols] )
// or
// void display( size_t rows, size_t cols, double a[][cols] )
// or
// void display( size_t rows, size_t cols, double ( *a )[cols] )
{
for ( size_t i = 0; i < rows; i++ )
{
for ( size_t j = 0; j < cols; j++ ) printf( "%lf", a[i][j] );
putchar( '\n' );
}
}
int main(void)
{
while ( 1 )
{
size_t m, n;
printf( "Enter numbers of rows and columns (0 - exit): " );
if ( scanf( "%zu%zu", &m, &n ) != 2 || m == 0 || n == 0 ) break;
double a[m][n];
putchar( '\n' );
init( m, n, a );
display( m, n, a );
putchar( '\n' );
}
return 0;
}
Its output might look like
Enter numbers of rows and columns (0 - exit): 2 3
0.0000000.0000000.000000
0.0000000.0000000.000000
Enter numbers of rows and columns (0 - exit): 3 4
0.0000000.0000000.0000000.000000
0.0000000.0000000.0000000.000000
0.0000000.0000000.0000000.000000
Enter numbers of rows and columns (0 - exit): 0 0
Within the both functions the third parameter is adjusted to the pointer type double ( *a )[cols]
. It is not the same as double **a
.
If you will write for example the following program
#include <stdio.h>
#define M 2
#define N 3
int main(void)
{
int a[M][N] =
{
{ 1, 2, 3 },
{ 4, 5, 6 }
};
int **p = ( int ** )a;
p[0][0] = 10;
return 0;
}
then it will have undefined behavior because p[0]
considers the value stored in the element a[0][0]
(or the combined value stored in elements a[0][0]
and a[0][1]
depending on the size of the pointer) that is the value 1 as a pointer value and try to access the memory at address 1 in the expression p[0][0]
.