tags:

views:

52

answers:

2

related to http://stackoverflow.com/questions/2520535/gcc-multi-dim-array-or-double-pointer-for-warning-free-compile , is there a way to return so-called "decayed array pointer" from a function? in summary (suppose 2 dim array) returning int (*a)[5] format rather than int** format?

as far as I see, when returned int** pointer is sent to another function waiting (int*)[] parameter, it is not working correctly.

+4  A: 

Yes, but the syntax won't look nice

int(*f())[5] {
  static int a[1][5] = { { 1, 2, 3, 4, 5 } };
  return a;
}

Basically, it's just your a replaced by f() (a function). Using a typedef it becomes more readable

typedef int inner_array[5];

inner_array *f() {
  // like before ...
}

Notice that to denote the abstact type, without a name, you need to write int(*)[5]. That is, you just erase the name. (int*)[5] is not valid syntax.

You are right - you can't return int** because this means you have a pointer to a pointer. Accessing with f()[A][B] would read from the address the returned pointer gives, and then read again from the address given by that pointer in turn. But in fact, the array pointer you return points only to one memory block, so if you would make two indirections, you would try to reinterpret data as being pointers.

Contrary, if you return a int(*)[5] and do f()[A][B] you will not read any value from the address returned by the pointer. Instead, you merely add the offset A to the address, and adjust the type from int(*)[5] to int[5] to have an array that refers to memory at the adjusted address. The next index will then again adjust by B and since it operates on a int* then (after the array decayed), not anymore on an array pointer, it will then read the content stored at the adjusted address, to finally yield the int. This is an important difference of non-array pointers and array pointers.

You can experiment with this, if you want. Consider these two snippets. One will probably crash, but the other probably won't (but both yield undefined behavior, so this shouldn't be done in real programs)

int *pi = 0; 
int(*pa)[5] = 0;

int i = *pi; // read int stored at null-pointer address!
int *a = *pa; // does not read any data from address, just adjusts the type!
Johannes Schaub - litb
A: 
struct thing {
   int A[10][10];
};

typedef struct thing thing_t;

thing_t f1(void) {
    thing_t t;
    ...
    return t;
}
thing_t * f1(void) {
   thing_t * tp;
   ...
   return tp;
}

Though, you're really going about this the wrong way.

nategoose