0

I'm new to C, trying to learn it by coding real things instead of isolated and naive book examples. I'm struggling a lot with understanding pointers correctly. My books aren't really helping.

I've got an array of pointers which i'm initializing the following way:

struct Node **cols;
cols = (struct Node *) calloc(N_RESTRICTIONS, sizeof(struct Node *));
// for loop malloc-ing each cols[0..N_RESTRICTIONS] here

Which seems ok. I need another variable, say upper_nodes, which initially points to the same nodes as cols, but that'll gonna be changing as the algorithm evolves, while cols does not change. I tried:

struct Node **upper_nodes;
*upper_nodes = *cols;

What i'm expecting is: upper_nodes address is not the same as col's (they're different variables), but as the first pointed value in each one is the same due to the assignment, i now can index upper_nodes[i] just like i did with cols, and reassign it without affecting what cols[i] points to.

This isn't what's happening, i'm getting a segmentation fault and in the debugger i see the first value in both vars points to the same item, but after that upper_nodes has random values (like non-initialized, i'm sure that's what happens but i don't get it).

What i'm not getting here? What's the way to do this?

Bonus question: I see that the last chunk of code above does the same as:

struct Node **upper_nodes = cols;

I don't understand this either. I would now expect upper_nodes and cols to have the same address but they haven't, which seems to say i'm not even understanding how variables work.

roirodriguez
  • 1,685
  • 2
  • 17
  • 31
  • 1
    Please [don't cast the result of `malloc` or `callor`](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc), or any function returning `void *`. Especially if you get the cast wrong like you do. – Some programmer dude Aug 12 '23 at 08:18
  • 1
    Note that `*upper_nodes = *cols` is the same as `upper_nodes[0] = cols[0]`. Which won't work well if `upper_nodes` isn't initialized. Perhaps you just want `struct Node *upper_nodes;` and `upper_nodes = cols[0]`? – Some programmer dude Aug 12 '23 at 08:20
  • About your first comment: Oh, i see... I'm reading tons of code casting like that and that's why i developed the habit, which i'm now dropping. Thanks. Your second comment i'm still thinking :-) – roirodriguez Aug 12 '23 at 08:23
  • 1
    And if you do cast the result of malloc, you need to use the correct type. It should be `(struct Node **)`, the same type as the variable you're assigning to. You should have gotten a warning from your code. – Barmar Aug 12 '23 at 08:25
  • So, isn't this correct? https://stackoverflow.com/questions/12579719/dynamic-allocation-of-array-of-pointers – roirodriguez Aug 12 '23 at 08:30

2 Answers2

2

Pointers are really what their name implies: They are a thing that points to another thing.

It becomes really clear if you draw it all out on paper:

+------+     +---------+     +------------+------------+-----+
| cols | --> | cols[0] | --> | cols[0][0] | cols[0][1] | ... |
+------+     +---------+     +------------+------------+-----+
             | cols[1] |
             +---------+
             | .       |
             | .       |
             | .       |
             +---------+

Then when you say that you

expect upper_nodes and cols to have the same address

If you mean that you expect &upper_nodes to be equal to &cols then that not correct. Drawn out it will look like:

+--------------+     +-------------+
| &upper_nodes | --> | upper_nodes | --\
+--------------+     +-------------+   |     +---------+-----+
                                        >--> | cols[0] | ... |
+-------+     +------+                 |     +---------+-----+
| &cols | --> | cols | ----------------/
+-------+     +------+

So &upper_nodes point to the variable upper_nodes. And &cols point to the variable cols.

And both upper_nodes and cols point to cols[0].

So &upper_nodes != &cols, but upper_nodes == cols.

Note that the above diagram assumes

struct Node **upper_nodes = cols;
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Ok, as i said in my question, i weren't understanding this at all and that's why drawing didn't help. I played a bit with gdb and dissassemble with a basic example and quickly review my books afterwards. After doing so i finally got it. Thanks, i'm marking this as correct, i really appreciate your help. – roirodriguez Aug 12 '23 at 08:49
1

As mentioned in the comments, *upper_nodes = *cols just copies one pointer, not the whole array.

You can do it with a loop:

for (int i = 0; i < N_RESTRICTIONS; I++) {
    upper_nodes[i] = cols[i];
}

or you can copy them all at once with memcpy():

memcpy(upper_nodes, cols, N_RESTRICTIONS * sizeof *cols);
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • Marked @Some programmer dude's answer as correct, but i need to do what you say to solve my problem, after i really understood it. Hope i've got the opportunity to bring up your deserved reputation up soon, really appreciated your help. – roirodriguez Aug 12 '23 at 08:55