2

I've made this simple program to test struct, pointers and malloc() of C programming:

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

 typedef struct l {
    unsigned val;
    struct l * next;
} list;


typedef struct cont {
    list ** mat;
    unsigned riga;
} container;


int main(){

    container * c = (container *)malloc(sizeof(container));
    c->riga = 3;
    c->mat = (list**)malloc(sizeof(list*)*3);

    for(int i = 0; i<3 ;i++){
        c->mat[i] = NULL;
    }

    c->mat[0] = (list *)malloc(sizeof(list));
    c->mat[0]-> val = 4;
    c->mat[0]-> next = NULL;

    printf("val row 0: %d\n", c->mat[0]->val);

    /*************************/

    list * ca = c->mat[1];
    ca = (list *)malloc(sizeof(list));
    ca->val = 2;
    ca->next = NULL;

    printf("val row 1: %d\n", c->mat[1]->val);

    return 0;
}

The problem is that I get a segfault on the 2nd printf() ... shouldn't c->mat[1] and ca be equivalent?

Shouldn't they point to the same allocated memory?

Initially c->mat[1] is NULL so is ca = c->mat[1] = NULL, after ca= malloc() it points to something else ... what about c->mat[i]? And what if I do the viceversa?

alk
  • 69,737
  • 10
  • 105
  • 255
Levenlol
  • 305
  • 5
  • 17
  • How about trying it yourself by perhaps printing the values or with a debugger? You'll find out. – edmz Mar 18 '16 at 17:29
  • 4
    [do not cast the return value of `malloc`](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – Antti Haapala -- Слава Україні Mar 18 '16 at 17:33
  • Change `c->mat[1]` to be `ca` and it'll work as expected. You allocated to `ca` not to `c->mat[1]`. This initialisation `list * ca = c->mat[1];` is useless as in the next line you overwrite `ca`'s value. – alk Mar 18 '16 at 17:35
  • And BTW, you'd do everybody a favour increasing readability of your code by indenting it properly!-) – alk Mar 18 '16 at 17:38

3 Answers3

3

ca is a copy of c->mat[1], so when you later change ca to point to the malloc-ed list it is not a copy of c->mat[1] anymore and especially if you modify ca you do not also modify c->mat[1].

If ca were not a pointer but an int you would not expect that, or would you assume that a was 2 in the following example?

int a = 3;
int ca = a;
ca = 2;

Of course, if ca is a copy of c->mat[1] and you change *c then you also change *(c->mat[1]).

Werner Henze
  • 16,404
  • 12
  • 44
  • 69
2
list * ca = c->mat[1];

set ca to NULL

ca = (list *)malloc(sizeof(list));

set ca to point to the new memory given from malloc, but c->mat[1] still point to NULL.

you can have a pointer to the pointer c->mat[1]:

list ** ca = &c->mat[1];
(*ca) = malloc(sizeof(list));
(*ca)->val = 2;
(*ca)->next = NULL;

and don't forget to use free().

1

The code for c->mat[0] is correct, and could be used for c->mat[1].

Or you code fix the c->mat[1] code by assigning the results of malloc to c->mat[1] and then copy the pointer to ca

c->mat[1] = malloc(sizeof(list));
list *ca = c->mat[1];
ca->val = 2;
ca->next = NULL;

Another solution is to copy ca to c->mat[1] at the end

list *ca = malloc(sizeof(list));
ca->val = 2;
ca->next = NULL;
c->mat[1] = ca;
user3386109
  • 34,287
  • 7
  • 49
  • 68