1
#include <stdio.h>
#include <conio.h>

#define     GRID_X              30
#define     GRID_Y              20

unsigned char board[GRID_Y][GRID_X];

void draw_board( unsigned char ** );
void print_board( unsigned char ** );

int main()
{
    draw_board( board );
    getch();
    return 0;
}

void draw_board( unsigned char **board )
{

    unsigned int  r_itr = 0,
                  c_itr = 0;

    if( NULL == board )
    {
        printf( "cannot create board..!!" );
        exit(0);
    }

    r_itr = 0;

    for( c_itr = 0; c_itr < GRID_X; ++c_itr )
    {
        board[ r_itr ][ c_itr ] = '+'; /* <- crashing here  */
        board[ r_itr + ( GRID_Y-1 ) ][ c_itr ] = '+';
    }

    c_itr = 0;

    for( r_itr = 0; r_itr < GRID_Y; ++r_itr )
    {
        board[r_itr][c_itr] = '+';
        board[ r_itr ][ c_itr + GRID_X-1 ] = '+';
    }

    print_board( board );
 }

void print_board( unsigned char **board )
{
    int r = 0,
        c = 0;

    for( r = 0; r < GRID_Y; ++r )
    {
        for( c = 0; c < GRID_X; ++c )
        {
            printf( "%c", board[r][c] );
        }

        printf("\n");
    }
}

The above code is crashing at the point I mentioned via comment ( crashing here ). I did all the possible boundary-checking ( based on my understanding ), I am still not able to detect the reason for crashing? I used GNU GCC compiler and code blocks IDE.please help?

CoolToshi45
  • 155
  • 2
  • 10
  • 3
    The data type of your function parameter is wrong. `board` is not a `unsigned char **`; its an array of arrays. They are NOT synonymous. – WhozCraig Sep 13 '14 at 03:27
  • 2
    Why are you passing `board` to all your functions as argument, when it is a global variable? – ani627 Sep 13 '14 at 03:28
  • i know its weird but its actually not a global i made it to express my doubt in a simple manner. – CoolToshi45 Sep 13 '14 at 03:31
  • 1
    So many C beginners think an array will decay to a pointer when they pass it, but it decays only once, so a 2D array wouldn't decay to a pointer to pointer. – jfly Sep 13 '14 at 03:38

2 Answers2

2

You should use:

void draw_board( unsigned char board[][GRID_X] )

or

void draw_board( unsigned char (*board)[GRID_X] )

Update

Why does the function draw_board, as defined in the question, cause problems?

Let's say you have

char b[2][3] = {{0}, {0}};

The layout of memory for the array is:

<--- b[0]     --->|<--- b[1]     --->

a1    a2    a3    a4    a5    a6
+-----+-----+-----+-----+-----+-----+
| 0   | 0   | 0   | 0   | 0   | 0   |
+-----+-----+-----+-----+-----+-----+

where a1 ... a6 are addresses.

When you pass b to a function, it decays to a pointer and the value passed to the function is a1.

Let's say you have a function foo declared as:

void foo(char** b);

When you pass the b to foo, the value of b in foo is a1.

b[0] = *b = *a1

The data being held at address a1 is now being treated as a char*. If the size of a pointer is 4 bytes,

b[0] = 0;

If you dereference b[0], such as in an expression b[0][0], you will get undefined behavior.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • ok i see data type mismatch is there. but how it leads to crashing? – CoolToshi45 Sep 13 '14 at 03:29
  • @user2070804 because its **wrong**. you're using the wrong pointer type and thus have an invalid alias, Therefore your program invokes *undefined behavior* when using that pointer. Thus the program is *ill-formed* and *may* crash.(and in this case, is highly likely to do just that). +1, btw, on the answer – WhozCraig Sep 13 '14 at 03:30
  • ill-formed and may crash.ok i got you.still didnt explain why its crash. the statement "board[r_itr][c_itr]" will alwats read one byte right? – CoolToshi45 Sep 13 '14 at 03:36
0

The problem is that for 2-d matrices, the expressions unsigned char[][] and unsigned char ** are not compatible. The C language FAQ and this other question will explain the differences.

When you compiled your code, you should have seen a warning like the following. This is from gcc:

warning: passing argument 1 of 'draw_board' from incompatible pointer type

If you want to fix the problem and keep draw_board() the same, you need to declare board as unsigned char ** and allocate memory like so:

#include <stdio.h>
#include <stdlib.h>
//#include <conio.h>

#define     GRID_X              30
#define     GRID_Y              20

//unsigned char board[GRID_Y][GRID_X];
unsigned char **board;

void draw_board( unsigned char ** );
void print_board( unsigned char ** );

int main()
{
    board = (unsigned char **) malloc(sizeof(unsigned char *) * GRID_X);
    int i;
    for (i = 0; i < GRID_X; i++)
    {
        board[i] = (unsigned char *) malloc(sizeof(unsigned char) * GRID_Y);
    }

    draw_board( board );
    //getch();
    return 0;
}
Community
  • 1
  • 1
stackoverflowuser2010
  • 38,621
  • 48
  • 169
  • 217