There are two answers to your question, depending on whether you are
using the gcc compiler, or insisting on ANSI standard C that is
portable to all compilers. Since the code you have presented will not
compile in ANSI standard C, I will present the gcc answer first, as
you probably would not have written the code the way you did in your
question if your compiler was rejecting it.
In recent versions of the GNU gcc compiler, what you want to do is not
too difficult. All you have to do is define your function so that the
number of rows and columns in the array are passed as separate
parameters before the array itself is passed. (This is necessary
because two-dimensional arrays are not really high-level objects in C;
gcc has extensions to C that make it possible to work with them more
conveniently, but at the root of things, a two-dimensional C array is
really just a pointer to the first element. So passing the number of
rows and columns is necessary to help the gcc C extensions to do their
work and make the array act a bit like a two-dimensional array in a
high-level language.)
See the following code, which has been tested:
void myfunction(int rows, int cols, int topass[rows][cols]);
int main(int argc, char *argv[])
{
int i = 10;
int j = 20;
int topass[i][j];
myfunction(i, j, topass);
}
void myfunction(int rows, int cols, int topass[rows][cols])
{
topass[0][0] = 1;
}
For more information about gcc and its extensions to the C language, see:
gcc C extensions
http://gcc.gnu.org/onlinedocs/gcc-2.95.3/gcc_4.html#SEC75
Now, the above works great with gcc, and gcc may be all you ever use.
But just to be sure you understand that what you are doing is not ANSI
standard portable C, the second half of my answer focuses on how to do
this correctly without the special extensions to C included only in
gcc:
* * *
First of all, the const keyword in ANSI C does not provide a way to declare
arrays of variable size; however, the code you have written will compile
successfully under gcc 3.1.1 and perhaps other compilers that are somewhat
relaxed about these things. In strict ANSI C you would need to write:
int topass[10][20];
Or use macros to make it a little more elegant:
#define ROWS 10
#define COLUMNS 20
int topass[ROWS][COLUMNS];
Or, if the number of rows and columns is not known at compile time,
allocate the array on the stack:
int *topass = alloca(10 * 20 * sizeof(int));
Now, as to the subject of passing the array to a function, C does not really
have a high-level array type; the size of each dimension of the array is
unknown at runtime. This hurts the most when the array has more than one
dimension, like this one does. The "array" you have declared is actually just
a pointer to the first element in the array. If you must have the ability
to pass a variety of two-dimensional arrays of different dimensions to the
same function, then you will need to explicitly pass the dimensions of
the array to the function, which will need to calculate the right
offset in the array every time an element in the array is wanted:
myfunction(topass, i, j);
The function must be written like so:
void myfunction(int *topass, int i, int j)
{
topass[i * row + col] = value you want to assign at this row and col;
}
A little confusing? You can make this a bit simpler with a macro:
#define ROWCOL(array, row, col) (array)[(row) * i + (col)]
void myfunction(int *topass, int i, int j)
{
ROWCOL(topass, row, col) = whatever you want to assign;
}
Thanks for the opportunity to answer this question. |
Clarification of Answer by
majortom-ga
on
15 Feb 2004 12:46 PST
If you are using gcc exclusively, you don't have to use the
"topass[i * row + col]" method. You can use the method in
the first part of my answer instead.
If you are following strict ANSI C, though, then you can't
write this:
/* WRONG in ANSI C, but gcc allows it */
void myfunction(int rows, int cols, int topass[rows][cols])
The language simply does not allow it. You are only allowed to do this:
/* Allowed in ANSI C */
void myfunction(int topass[10][20])
But that would be an array of a fixed number of rows and columns, and
you specified that the array might have any size. Since ANSI C has no
provision
for passing a simple two-dimensional array of integers to a function,
you must pass a pointer to the first integer and calculate the offset
each time you want to access one. For convenience, passing the name of
the array implicitly passes a poitner to the first integer in it.
Alternatively, you could create your array differently in the first place:
int data[10 * 20];
int *dataPointers[10];
int i;
for (i = 0; (i < 10); i++) {
dataPointers[i] = data + i * 20;
}
myfunction(rows, cols, dataPointers);
You could then write myfunction as:
void myfunction(int rows, int cols, int **dataPointers)
And you would then be allowed to refer to
dataPointers[row][col] in a more natural fashion -- but
the price is that you must set up an array of pointers
to each row of data, as shown above, and pass that to
myfunction. It is usually just as easy to follow my
original ANSI C suggestion of calculating the offset each time.
And of course if you stick to gcc you can follow my first
set of recommendations, which make all of this convenient,
and forget about the tough parts entirely.
|