In the generateSpiral
function you make the structures pointer point to the local variable data
, but when the function returns data
goes out of scope so the pointer now points to unallocated memory leading to undefined behavior.
But that's not your only problem: A second problem is that a pointer to a pointer is not the same as an array of arrays, the memory layout is different.
For the last part, lets check an example. Lets say we have the following declaration
int a[2][2];
In memory it will look something like this:
+---------+---------+---------+---------+
| a[0][0] | a[0][1] | a[1][0] | a[1][1] |
+---------+---------+---------+---------+
In other words, all data is contiguous.
If you, on the other hand have a declaration like
int **p;
and allocate data for it correctly, it will look something like
+------+------+-----+
| p[0] | p[1] | ... |
+------+------+-----+
| | |
| | v
| | ...
| v
| +---------+---------+-----+
| | p[1][0] | p[1][1] | ... |
| +---------+---------+-----+
v
+---------+---------+-----+
| p[0][0] | p[0][1] | ... |
+---------+---------+-----+
The memory is no longer contiguous. There is no longer any maximum size, a pointer points to a contiguous area of memory, but there is no way of knowing how big that area is. You have to keep track of it yourself.
The simple solution to both the problems is to use only pointer to pointer, and then allocate dynamically of the heap:
int **data;
// First allocate memory for `size` number of pointers
// I.e. we allocate an "array" of pointers
data = malloc(size * sizeof(int *));
// Then allocate each entry in the above allocated "array"
// I.e. make each pointer in the "array" point to an "array" of `int`
for (int i = 0; i < size; ++i)
data[i] = malloc(size * sizeof(int));
Now the local variable data
can be used directly to assign to spiral.data
.
But there is a catch: In Java you don't have to free memory you allocate, it's handled automatically. In C it's not handled automatically, you have to manually free the memory you allocate or you will have a memory leak.
Freeing the memory can be done like
// First free all the "sub-arrays"
for (int i = 0; i < size; ++i)
free(spiral.data[i]);
// Then free the top-level "array"
free(spiral.data);
Regarding pointers, a pointer can point to any memory address, and there is really no safety or checking that it points to a valid location. Also, C does not do deep copying of values and structures, if you have a pointer and make it point somewhere, then the compiler or runtime system doesn't make a copy.
And about scoping, Java has local variables as well, and just like in C when a function returns those go out of scope. The difference between Java and C, is that if you return a reference to a local object, then Java keeps track of that and keep the object in memory as long as there are references to the object. C doesn't have references, a pointer is just an integer whose value is an address in memory, and the data pointed to have no idea that there are pointers to it or how many.