5

I'm a beginning programmer who is confused with passing a two dimensional array to a function. I think it may just be a simple syntax problem. I've looked for an answer, but nothing I've found seems to help, or is too far above my level for me to understand.

I identify the array and the function in the main function as, and after initializing it, attempt to call it:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

int const ROWS = 8;
int const COLS = 8;

int main(int argc, char** argv) {

char board[ROWS][COLS];

bool canReach(char board[][], int i, int j);

//initialize array

//values of i and j given in a for loop

canReach(board, i, j);

return (EXIT_SUCCESS);
}

While writing the function outside the main function, I defined it exactly the same as I did in the main function.

bool canReach(char board[][], int i, int j){
//Functions purpose
}

When I attempt to build the program, I'm given this error twice and the program does not build:

error: array has incomplete element type 'char[][]'
bool canReach(char board[][], int i, int j)
                        ^

Please note that I'm trying to pass the entire array to the function, and not just a single value. What can I do to fix this problem? I would appreciate it if it didn't have to use pointers, as I find them quite confusing. Also, I've tried to leave out things that I thought weren't important, but I may have missed something I needed, or kept in things I didn't. Thank you for your time in helping out this starting programmer!

4
  • 1
    In C constants are actually variables the programmer guarantees not to change. For such as your array-size, it is the better way to #define them as macros. Note this its different from C++. Commented Jul 24, 2015 at 22:22
  • Please format your code properly. Commented Jul 24, 2015 at 22:23
  • The error is saying with reference to 2nd [] an array of what (How big is thing thing). Therefore you MUST specify the size of the array, for at least the 1st []. Alternatively you could pass a pointer to 0,0 and the 2 sizes. Commented Jul 24, 2015 at 22:49
  • Array indexes should be type size_t. Commented Jul 24, 2015 at 22:52

3 Answers 3

4

You can just pass arrays as function arguments with definition of their size.

bool canReach(char board[ROWS][COLS], int i, int j);

When the size is unknown, pointers are the way.

bool canReach(char* board, int i, int j);

You should know, that arrays != pointers but pointers can storage the address of an array.

Sign up to request clarification or add additional context in comments.

6 Comments

From what I remember of C classes, pointers are one of the most important things to master...
@LaurentS.: Yes, if you do not fully understand about pointers in C, you should not even think about writing code intendend to be actually used.
This comment helped me understand pointers better, I think. If I was to use the pointer method, then within the function, would I call to a specific place in the array the same way as I would in the main function ie. board[i][j];
With the pointer you got the address of the first element in your array. Now you have to work one-dimensional, but know: all elements are in row. F.e. given array x[2][3] is in memory x[0][0], x[0][1], x[0][2], x[1][0], x[1][1], x[1][2].
@Youka did you mean in the second example: bool canReach(char** board, int i, int j); and bool canReach(char* board[], int i, int j);? With char *board you can't access a 2d array like this board[0][0]
|
2

Here is a demonstrative program

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>

bool canReach( int n, int m, char board[][m] )
{
    for ( int i = 0; i < n; i++ )
    {
        for ( int j = 0; j < m; j++ )
        {
            board[i][j] = 0;
        }
    }

    return printf( "Hello SaarthakSaxena" );
}    

int main( void )
{
    const int ROWS = 8;
    const int COLS = 8;

    char board[ROWS][COLS];

    canReach( ROWS, COLS, board );

    return EXIT_SUCCESS;
}

Its output is

Hello SaarthakSaxena

Comments

0

Defining a function inside another function (here: main) is not allowed in C. That is an extension of some compilers (e.g. gcc), but should not be used.

You have to specify the dimension of the array. C arrays do not have implicit size information as in HLL.

It also is not a good idea to use const variables for array dimensions in C. Instead

#define ROWS 8
#define COLS 8

Assuming i and j are the indexes of an element in the array, you can use the signature:

bool canReach(size_t rows, size_t cols, char board[rows][cols],
        size_t i, size_t j);

This allows to pass arrays of (run-time) variable size to the function. If the dimensions are guaranteed fixed at run-time:

bool canReach(char board[ROWS][COLS], size_t i, size_t j);

But only if using the macros above. It does not work with the const variables.

Both versions tell the compiler which dimension the array has, so it can calculate the address of each element. The first dimension might be omitted, but there is nothing gained and it would imhibit optional bounds checking (C11 option). Note the 1D-case char ca[] is just a special version of this general requirement you can always omit the left(/outer)most dimension.

Note I changed the types to the (unsigned) size_t as that is the appropriate type for array-indexing and will generate a conversion warning if properly enabled (strongly recommended). However, you can use int, but have to ensure no value becomes negative.

Hint: If you intend to store non-character integers in the array or do arithmetic on the elements, you should specify the signed-ness of the char types. char as such can be either unsigned or signed, depending on implementation. So use unsigned char or signed char, depending what you want.

8 Comments

enum dim { ROWS=8, COLS=8 }; is even better: gdb understands enumerations and will print ROWS and COLS for variables declared with the type enum dim, and executing the line enum dim x = 20; and printing its value in gdb will print (unknown: 20). As a debugging aid, the (unknown: XXX) output is wonderful for catching errors such as writing beyond the ends of arrays.
@ChronoKitsune: enum constants are int by default, as much as the enum itself. I - in general - do not recommend to use enum for unrelated constants, as that implies a binding which does not exist naturally: Nothing wrong with macros in C; this is not C++. size_t is the most appropriate type for array indexing. Btw. gdb is also aware of such simple macros. Your approach would imply each dimenion variable can get either of ROWS or COLS, so you actually would have to create one enum with single constant per dimension. No, sorry, but I disagree.
"... and printing its value in gdb will print ..." You mean x by "its"? I think I do not get what you actually mean here. Please elaborate. As far as I see that, gdb will output (unknown: ...) for any value of the enum there is no constant defined. Sounds pretty useless, as you do not want to define a constant for every valid index value.
Suppose you have a C file with enum dim x = ROWS; in it. print x will display "ROWS" rather than "8" (you can use print /x ROWS to display "0x8" instead, if you wish). If you assign a different value to x that is not specified in enum dim, such as 20, then print x will display (unknown: 20). There is a slight flaw in my example since ROWS and COLS refer to the same value in this case, but in general, it works well when you have differing constants. That isn't the case with #define ROWS 8 as print /x ROWS will print "No symbol "ROWS" in current context."
It will just print that for the exact match of the dimension For indexes 0..7 it will just print the (valid!) value as for an out-of-bounds value. OTOH, you have a signed integer for the dimension, not an unsigned, so gcc cannot even warn about conversion problems. Also, no one hinders be to use a different enum (e.g. confuse rows and cols) for the indexes. For printing macros: well, that works, I use it every day I debug my embedded project, e.g.: print /x *SPI1 - SPI1 being a macro. Perhaps you just don't add the correct ELF sections to your object?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.