0

I started learning C language a week ago. Just for the test I decided to write a tictactoe game.

I have a field.

int field[3][3];

And a function printField

void printField(int field[3][3]){
for(int i = 0; i < 3; i++){
    for(int j = 0; j < 3; j++){
        printf("%i", field[i][j]);
    }
    printf("\n");
}}

It's working in main like this:

int main(){
printField(field);}

BUT if I change

 void printField(int field){...}

or

void printField(int field[][]){...}

It gives me a bunch of errors:

subscripted value is neither array nor pointer nor vector                      
passing argument 1 of ‘printField’ makes integer from pointer without a cast
note: expected ‘int’ but argument is of type ‘int (*)[3]’

Why can't I pass the array like this? Are there any more ways to pass it?

shegeley
  • 85
  • 2
  • 8
  • Well `int field` declares `field` as a single `int` variable. That's clearly wrong, a single integer is not an array and definitely not an array of arrays. And `int field[][]` is simply not allowed, it should be either the way you have working, or `int (*field)[3]` (as indicated in the error message, and what the compiler really uses). – Some programmer dude Nov 10 '16 at 07:49
  • Note an array is passed as a pointer, so 'int field' for sure won't work, as you want to point to a number (first in array), not send the actual number. int* field, and int field[] are the same in c, the second is syntactic sugar for the codes readability. – kabanus Nov 10 '16 at 07:49
  • So, as I understood there is no way to make field reusable right? Even I already declared it and it's size I have to pass it's size again in printField() ? – shegeley Nov 10 '16 at 08:09

3 Answers3

3

The function is independent of any call to the function. So the function cannot guess from the rest of the program what the array size is. In the function body you have to have constants or variables to represent all dimensions.

You can use variables for this instead of fixed size:

void printField(int r, int c, int field[r][c])
{
    for(int i = 0; i < r; i++)
        for(int j = 0; j < c; j++)
            printf("%i", field[i][j]);

    printf("\n");
}

And to call the function:

printField(3, 3, field);

You can compute the dimensions from the array's name. Using a macro confines the ugly syntax:

#define printField(a) printField( sizeof(a)/sizeof((a)[0]), sizeof((a)[0]) / sizeof((a)[0][0]), (a) )

int f1[3][3] = { 0 };
printField(f1);

int f2[4][5] = { 0 };
printField(f2);
M.M
  • 138,810
  • 21
  • 208
  • 365
1

When you write an array as a function, the compiler will silently "adjust" that array and replace it with a pointer to the first element. So when you write void func (int x[3]) the compiler silently replaces this with void func (int* x) where the pointer points at the first item of the array.

The reason why C was designed this way is not avoid having large arrays getting pushed on the stack, which would be slow and memory-consuming.

In your case, the function void printField(int field[3][3]) gets silently adjusted behind the lines to

void printField(int (*field)[3])

which is an array pointer pointing at the first element, which is a int[3] array. Which can still be used as field[i][j], so all is well. You can pretend that it is an array inside the function.


void printField(int field) obviously doesn't make any sense. This is not an array but a single item. You can't use [] on a plain int and that's what the compiler is telling you: "subscripted value is neither array nor pointer nor vector".


void printField(int field[][]){...} doesn't work either, because an empty [] means "declare an array of incomplete type". It can't be used before the array size is defined.

In case of void printField(int field[]) this happens to work because of the above mentioned "array adjustment" rule of functions. The compiler doesn't have to know the array size, because it just replaces the array with int* anyway.

But in the case with two unknown dimensions, the compiler tries to adjust int field[][] to int (*field)[]. This is a pointer to an array of incomplete type and can't be used by the function.

You could however do int field[][3] and it will work just fine.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • But I've already declared int field[3][3]. Why do I have to pass it with it's size again? What if I want to change field size? – shegeley Nov 10 '16 at 08:05
  • @ГригорийШепелев The function declaration and definition must match. If you want variable size, you should declare the function as `void printField(int x, int y, int field[x][y])` – Lundin Nov 10 '16 at 08:09
  • thanx you, @Lundin. that's what I'be been looking for. – shegeley Nov 10 '16 at 08:22
-4

In C You can pass you array like this

void printField(int **field){...}

it's much better to work with pointeur than to work with static array :)

fhenri
  • 1
  • Yeah, that's actually what I've been looking for but what type should I cast printField(field) in main? – shegeley Nov 10 '16 at 08:01