1

I have the following typedef:

typedef struct cell_t {
    int x; // x coord of this cell                                                                                 
    int y; // y coord of this cell                                                                                 
    int neighbour_count; // Size of the following array                                                            
    struct cell_t **neighbours; // array of pointers to neighbours                                                 
} cell_t;

and some code to initialize this type (neighbour_count and neighbours are to be set later)

cell_t *create_cell(int x, int y){
    cell_t *cell = malloc(sizeof(cell_t));
    cell->x = x;
    cell->y = y;

    return cell;
}

I have myfun to initialize the neighbours and neighbour_count variables for a matrix of cell_t, which it reads from some external source.

int myfun(cell_t ***cells, int width, int height){
    for (int x = 0; x < width; x++) {
        for (int y = 0; y < height; y++) {
            // Read data from source, including the long `list_size`

            cells[x][y]->neighbour_count = (int) list_size; // This segfaults
        }
    }
}

So in my main, I have the following:

int width = 3, height = 3;

cell_t *cells[width][height];

for (int x = 0; x < width; x++){
    for(int y = 0; y < height; y++){
        cells[x][y] = create_cell(x,y);
    }
}

myfun(cells, width, height);

When setting the neighbour count, it segfaults (as marked in the third block of code).

What I think I'm doing is that in my main I initialize an empty matrix of pointers to cell objects, and then loop through width and height, creating cells, and storing the pointers to them in the matrix. Then in myfun, I'm simply accessing a the variable neighbour_count of these cells and setting it. But apparently I'm mistaken, as it segfaults (not always on the first loop though, but generally quite quickly).

I'm thinking perhaps I did something wrong such that the matrix cells does not actually contain pointers to cell_t structs. But I can't see what I'm doing wrong.

I am getting a warning that "passing argument 1 of ‘myfun’ from incompatible pointer type", and that it should instead be of type cell_t * (*)[(sizetype)(height)]; perhaps that helps? I would expect there not to be a problem, as struct_t *** should be good for a 2d array of pointers, no?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Lara
  • 2,594
  • 4
  • 24
  • 36
  • What are initial values for x,y in your for loops? `int x; x < width; x++` – rafix07 Feb 20 '20 at 13:25
  • @rafix07 well spotted, I fixed those lines now (but the problem remains) – Lara Feb 20 '20 at 13:28
  • 2
    `cell_t *cells[width][height];` is not compatible with `cell_t ***cells` and your compiler should tell you as much. Furthermore you don't seem to allocate memory for `neighbours` anywhere. Consider [Correctly allocating multi-dimensional arrays](https://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays) instead. – Lundin Feb 20 '20 at 13:28
  • The memory allocation for neighbours isn't in this code because it segfaults before that anyway. But why are these types not compatible? Seems to me that a pointer to `cell_t` should be `cell_t *`, and an array of such things `cell_t **` and a 2D array of such things `cell_t ***`. Perhaps this is the mistake I'm making? – Lara Feb 20 '20 at 13:33
  • A pointer is not an array. A pointer to pointer is not a 2D array. Nor can it point to a 2D array. It's all explained in the link I gave. – Lundin Feb 20 '20 at 13:52

2 Answers2

2

The type of the first function parameter

int myfun(cell_t ***cells, int width, int height){

and the type of the supplied argument

myfun(cells, width, height);

do not correspond each other. The function argument declared like

cell_t *cells[width][height];

is implicitly converted to pointer to its first element. That is it has the type cell_t * ( * )[height].

Thus the corresponding function should be declared like

int myfun( int width, int height, cell_t * cells[][height] ){

or like

int myfun( int width, int height, cell_t * ( *cells )[height] ){

that declares the same function.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

One thing is not correct in your code that i recognize is the definition of pointer.

cell_t *cells[width][height];

This defifnition is not for pointer that points to an array 2D. Like @Lundin commented above, it is not compatible with cell_t ***cells. If you want to define a pointer that points to an array 2D, you can use the code below:

cell_t cells[width][height];
cell_t *ptr = &cells;

The pointer ptr is compatible with ***cells in your code

Hitokiri
  • 3,607
  • 1
  • 9
  • 29
  • What I'm trying to achieve is that `cells` is a 2D array of pointers, namely pointers to `cell_t`s. How would I go about doing that? I assumed `cell_t cells[width][height]` would be a 2D array of `cell_t`, so `cell_t *cells[width][height]` would be a 2d array of pointers to `cell_t`. – Lara Feb 20 '20 at 13:46