There are many misconceptions about arrays, multidimensional arrays, and pointers. I will try to explain the differences between them, then answer the question. Below, T
denotes a type name.
T x[3]; /* the type of x is "array of T" */
x
is an array. It has three elements. Each element is a T
.
T *x[3]; /* the type of x is "array of pointer to T" */
x
is an array. It has three elements. Each element is a pointer-to-T
.
T (*x)[3]; /* the type of x is "pointer to an array of three Ts" */
x
is a pointer. It points to an array. The array has three elements. Each element is a T
T x[3][6]; /* the type of x is "array of array of six Ts" */
x
is an array. It has three elements. Each element is an array of six T
s. Hence x
is a multidimensional array, or more precisely, a two dimensional array, a 3×6 array of Ts.
And now, a very important rule in C: An expression with the type "array of T" is converted to the "pointer to T" that points to the initial element of the array object, except when it is the operand of the sizeof
or address operator. So,
void f(T*);
void g(void)
{
T x[3];
/* ... */
f(x); /* equivalent to f(&x[0]); */
}
The pointer to the first element of the array x
is passed as an argument in the function call f(x)
above. The array is not passed. It is not possible to pass an array directly to a function as an argument in C (it can be done indirectly by wrapping the array in a structure). Returning from a function has the same semantic: an array cannot be returned from a function (unless it is wrapped in a structure):
T *f(void)
{
static T x[3];
/* ... */
return x; /* Equivalent to return &x[0]; */
}
A pointer to the initial element of the array x
is returned.
Your array is defined as
static history_t history[3][6]; /* static is not relevant in this discussion */
Type of history
is "array of array of six history_t
s". It will be converted to "pointer to array of six history_t
s" when it is returned from a function, as discussed above. An object x
with the type "pointer to array of six history_t
s" is defined as
history_t (*x)[6];
To declare a function returning that type, the x
is replaced by the function declarator.
history_t (*get_history())[6]; /* function returning pointer to array of six history_ts */
The ()
has higher precedence than the *
, so no parentheses needed around get_history()
. To define such a function, the function body is added:
static history_t history[3][6];
history_t (*get_history())[6]
{
/* ... */
return history;
}