I'm working my way through 88 C Programs, relearning C after almost twenty-five years away (complicated by the fact there have been at least two major version revisions to the language itself since 1990, and I'm sure the Turbo-C I used then wasn't fully C89 compatible). I don't recall that the class I took did anything of consequence with two-dimensional arrays, and passing those into functions, with anticipation that I'll need to work on data without knowing the dimensions at compile time, is well along to making my head explode.
I'm using gcc (the version currently found in the standard repositories for Ubuntu 14.04), which I gather is supposed to support variable-length array declarations under C99 or C2011 standards, but the declarations I'm trying to use to make the function recognize the array without having to know the size at compile time are getting errors about "conflicting type". I'm compiling with warning set to max, using a tiny Python program to save having to type a long command line every time I need to compile (resulting command is gcc -std=c99 -pedantic -Wall -Wextra -o target target.c -lm
). Here are the prototype, caller lines, and function definition (the code is full of warning-inducing bad practices, too, where I copied it from the book; I'm not concerned about those at the moment, I'm interested in learning the sane way to do this so I don't have to use those ugly, confusing methods).
#include <stdio.h>
#include <stdlib.h>
/* ANSI prototypes */
void s2 (int, int, int*);
int main (void);
int main (void)
{
int one[5]={0,1,2,3,4};
int two[3][4] =
{
{0,1,2,3},
{10,11,12,13},
{100,101,102,103}
};
/* try to call s2, it won't work */
printf("\ncalling s2 \n");
s2(1, 5, one);
s2(3, 4, two); /* will be compiler warning */
}
void s2(int rows, int cols, int *x[rows][cols])
{
/* wants to use multiple square brackets; needs dimension info */
int i,j;
for (i=0; i<rows; i++)
{
for (j=0; j<cols; j++)
printf("%4i", x[i][j]);
}
}
This gives the following string of warnings and errors:
./gccm sotest
sotest.c: In function ‘main’:
sotest.c:22:3: warning: passing argument 3 of ‘s2’ from incompatible pointer type [enabled by default]
s2(3, 4, two); /* will be compiler warning */
^
sotest.c:6:6: note: expected ‘int *’ but argument is of type ‘int (*)[4]’
void s2 (int, int, int*);
^
sotest.c: At top level:
sotest.c:25:6: error: conflicting types for ‘s2’
void s2(int rows, int cols, int *x[rows][cols])
^
sotest.c:6:6: note: previous declaration of ‘s2’ was here
void s2 (int, int, int*);
^
sotest.c: In function ‘s2’:
sotest.c:32:7: warning: format ‘%i’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
printf("%4i", x[i][j]);
^
I've spent at least a couple hours digging through other similar-seeming questions here, reading articles on the Web, and generally trying to wrap my brain around the insanity that arises as soon as you need to pass a two-dimensional array to a function in C -- it's so simple in many other languages, and one-dimensional arrays are easy enough in C! I've found nothing that makes sense; the only sensible suggestion I've seen is to wrap the array in a Struct
, but those surely didn't exist for the first twenty or so years C was in wide use and I'm not sure how/why that makes it better.