0

Code:

struct Adjacent {
    char* c;
    int done_at; 
};

typedef struct Adjacent Adj; 

struct Container {
    Adj* m;
};

typedef struct Container Cont;

void alloc_stuff(Cont *cont) {
    cont = (Cont*)malloc(100 * sizeof(Cont));
    memset(cont, 0, 100 * sizeof(Cont));
    for (int i = 0; i < 100; ++i) {
        cont[i].m = (Adj*)malloc(50 * sizeof(Adj));
        memset(cont[i].m, 0, 50 * sizeof(Adj));
        cont[i].m->c = (char*)malloc(50 * sizeof(char));
        memset(cont[i].m->c, 0, 50 * sizeof(char));
        cont[i].m->done_at = 0;
    }
}

int main() {
    Cont* cont = NULL;

    alloc_stuff(cont);

    // cont still NULL here
}

Why is cont NULL after alloc_stuff()?

Sebi
  • 4,262
  • 13
  • 60
  • 116

2 Answers2

3

It is because of this line:

void alloc_stuff(Cont *cont)

The variable cont is a copy of the original pointer passed to the function.

If you want to modify the original pointer, you should use something like this:

void alloc_stuff(Cont **cont)
Nimantha
  • 6,405
  • 6
  • 28
  • 69
Patricio Loncomilla
  • 1,048
  • 3
  • 11
2

alloc_stuff(cont); passes the value of cont to alloc_stuff.

alloc_stuff does not receive any reference to cont. No changes made inside alloc_stuff can affect cont.

To change the value of cont in main, you should either modify alloc_stuff to return a pointer and use cont = alloc_stuff();, or you should modify alloc_stuff to accept a pointer to Cont * (so it would be a Cont **) and then modify the code inside it to use *cont where it is current using cont, after which you can call it with alloc_stuff(&cont);. (Or, where parentheses are needed, use (*cont) in place of cont.)

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • `*cont[i]->m = (Adj*)malloc(50 * sizeof(Adj));` gives `no operator = matches these operands. Operands are Adj and Adj* even though Cont has Adj* and not Adj (no pointer) – Sebi Apr 02 '21 at 18:08
  • 1
    @Sebi: Use parentheses as noted in the answer. `[` has higher precedence than `*`, so you need `(*cont)[i]->m`, not `*cont[i]->m`. Also, that error message suggests you are compiling as C++, not. Those are different languages and have different rules. A reference to a pointer might be more appropriate in C++ than a pointer to a pointer, and it would avoid the need for changing the code inside `alloc_stuff`; you would only need to change the declaration. – Eric Postpischil Apr 02 '21 at 18:11
  • Yes, I'm compiling as C++. `(*cont)[i]->m = (Adj*)malloc(50 * sizeof(Adj));` gives expression must have a pointer type. How does the syntax change (ref 2 pointer)? – Sebi Apr 02 '21 at 18:21
  • Nvm (*cont)[i]->m is of type Adj&. (*cont)[i].m is Adj* – Sebi Apr 02 '21 at 18:24