When you pass an array in C it is always passed by reference, i.e. through a pointer. The type of this pointer is not pointer-to-array, but pointer-to-first-element. For example, the code generator will handle void f(char[][10])
as if it where void f(char*)
. The array dimensions are lost. The parser, however, will complain if it sees f
declared twice so.
The motivation behind C was to have a powerful and portable assembler, not a new programming language. Multidimensional arrays are logical constructs that do not exist in the machine. Arrays are a way of thinking.
To pass the dimensions of arrays to functions C programmers traditionally use struct
s:
typedef struct array_tag {
int count;
char data[1]; /* actually data[count] */
} ARRAY;
typedef struct grid_tag {
int rows, columns;
char grid[1][1]; /* actually grid[rows][columns] */
} GRID;
void f(ARRAY* x)
{
int i;
for (i = 0; i < x->count; ++i) {
char c = x->data[i];
}
}
void g(GRID* x)
{
int i, j;
for (i = 0; i < x->rows; ++i)
for (j = 0; j < x->columns; ++j) {
char c = x->grid[i][j];
}
}
void h()
{
{
const int len = 100;
ARRAY* x = (ARRAY*) malloc(sizeof(ARRAY) + len * sizeof(char));
x->count = len;
f(x);
}
{
const int rows = 2, cols = 3;
GRID* x = (GRID*) malloc(sizeof(GRID) + rows * cols * sizeof(char));
x->rows = rows;
x->columns = cols;
g(x);
}
}
Yes, the malloc
expression in this example allocates few bytes too much. Therefore the GNU-compiler supports arrays of zero length for a long time, which are not allowed in C90.
C99 has gone one step further with flexible arrays. From ISO/IEC 9899:1999, Section 6.7.2.1, paragraph 16: "As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member." In C99 the ARRAY
and GRID
types can be declared as:
typedef struct array_tag {
int count;
char data[]; /* actually data[count] */
} ARRAY;
typedef struct grid_tag {
int rows, columns;
char grid[][1]; /* actually grid[rows][columns] */
} GRID;
and you can
assert(1*sizeof(int) == sizeof(ARRAY));
assert(2*sizeof(int) == sizeof(GRID));
Many people think C arrays are quirky. But they're also an elegant solution which allows the declaration of indefinitely complex arrays. It is known as the "K&R array equation". A good explanation can be found here.
Hope this helps.