I'm surprised no one has answered the question properly yet.
The simple reason your example doesn't compile is that it is illegal to return arrays from a function.
The following combinations are illegal in C:
[]() - cannot have an array of functions
()() - cannot have a function that returns a function
()[] - cannot have a function that returns an array
So you have to return a pointer to an array:
float (*pixels(void))[2]
{
static float x[2][2]= { {1,1},{2,2} };
return x;
}
Which reads as "pixels is a function that takes void and returns a pointer to an array 2 of float."
Eunice provided a similar answer (function returning a pointer to an array) but did not elaborate. Basically, an array not used in a sizeof or &/* operation is decayed by the compiler into a pointer. And this decay is NOT recursive- it only takes place once. So even though in this example x is a float [][], it decays into float (*)[], or "a pointer to array of float". Note that you will have to declare your array at the call site with the same type:
float (*y)[2] = pixels();
If your array size is dynamic, you also want to allocate the memory within the function in order for it to survive into the calling scope. Here is that version (using ** instead of (*)[] for brevity):
float **pixels(int nrows, int ncolumns)
{
// allocate the array of rows
float **array = malloc(nrows * sizeof(float *));
// iterate through the rows and malloc the appropriate size for the columns
for(int i = 0; i < nrows; i++) {
array[i] = malloc(ncolumns * sizeof(float));
}
return array;
}
To keep the multi-dim array contiguous in memory, you will want to implement the following:
// allocate a "mini array" nrow pointers deep, each the size of a pointer
int **contig_array = malloc(nrows * sizeof(int *));
// at the first pointer, allocate enough for the entire flattened multi-dim array
contig_array[0] = malloc(nrows * ncolumns * sizeof(int));
// Finally, iterate through each row (pointer) in the first 'mini array'
// and set the pointer to point to the address of the
// column start of the flattened array
for(i = 1; i < nrows; i++)
contig_array[i] = contig_array[0] + i * ncolumns;
To reinforce the concept of returning a pointer to an array, here is an example function taking a file name and returning an array of strings, using the "pointer to array" return type:
char (*file2array(char *filename))[]
{
FILE *fptr = fopen(filename, "r");
// determine lines in file first
fseek(fptr, 0, SEEK_END);
int filesize = ftell(fptr);
fseek(fptr, 0, SEEK_SET);
// malloc array
int numlines = 100000;
char (*newarray)[MAXCHARS+1] = malloc(sizeof *newarray * numlines);
// fill array
int i = 0;
while(fscanf(fptr, "%[^\n]%*c", newarray[i++]) != EOF);
fclose(fptr);
return newarray;
}