Today I was running one of my first C programs, and in the middle of it, I used a two-dimensional array. This time, after thinking about the syntax that is often learned without really understanding the execution logic, in this case, memory allocation at runtime. I come across an idea that seems somewhat confusing and that I share with the intention of checking if what I think is wrong and in this way there may be some correction that "lights" me on this matter.
I understand from what I have learned that a pointer is a variable that contains a memory address and allows access to it. This address can contain constant values or other variables. At this point, a pointer can point to another pointer because this pointer is also a variable, whose variability is determined by the memory location it points to.
Now, from here on I feel less sure of what I say and that is what I have doubts about.
When a pointer points to an array, it really does so to the first value, from which it is assumed that the successive elements of the array, being stored in contiguous positions, are modifiable when accessing with,
puntero[n]
taking into account that itn
is the magnitude of the displacement from the variable that the pointer actually points to.
About what I am saying I wonder:
- Is this correct?
- Do all arrays end with \0 or is this something unique to character arrays?
Continuing with the doubts, when assigning dynamic memory to a pointer.
- What really happens?
As far as I know, a dynamic memory pointer is a way to create an array and, with the logic of the previous paragraph, the pointer still points to a single memory location, which in this case is the first element of the array, so I conclude that what is really going on with the realloc()
. It is that the compiler is told
"This free zone memory can be used"
But in reality the nature of the pointer is not changing, since it continues to point to the first element and we move to the adjacent memory in the same way as was said before, with the difference that without allocating the memory this would not be possible because it is not available to use.
- Again, is this correct?
All in all, I get to what made me think of all this. It could be said that when declaring a two-dimensional array, if we see it as a matrix, the first array, of the same nature as the one described above, which determines the "rows" of the matrix, contains in turn pointers that point to the first element of other arrays. With which I think that the memory assigned to a two-dimensional array is only contiguous in two cases:
- The first, when we refer to the array that determines the "rows" of our matrix.
- Second, when we refer to each array pointed to by the pointers contained in the first array.
Therefore, the entire two-dimensional array would not be contiguous on the heap, but there would be a bunch of contiguous fragments randomly distributed on the heap, related to each other thanks to the pointers. I find this detail very fascinating and curious, to finish I must ask:
- What I say again, is correct?
It would be interesting to know that they can correct me or add something to what I say.
When we create a two- dimensional array via heap, all we need is an array of pointers :
All this code does is reserve memory for an array of 4 elements and initializes the memory in
0
. Each element is a pointer and its size in bytes will depend on whether the machine is 32-bit or 64-bit.On a 32-bit machine the expression
sizeof(int*)
would result in4
bytes (that would be the size of the pointer) and on a 64-bit machine the size would be8
bytes.Visually we would see it like this:
Here it is clear that the pointer
p
is pointing to the address0x016
(it is the base address of the array ).Then we must make each element of the array of pointers point to the base address of an array, which can be an array of
int
, ofchar
, etc.In this case it should be an array of integers:
This code does 2 things:
1.- It creates an array
int
dynamically and assigns it the base address inX
the position of the array of pointers.2.- Fill with values each position of the array to which each pointer points.
Visually we would see it like this:
In the image you can clearly see that each pointer points to the first element of an array.
In these two images we can observe two important things:
1.- The array of pointers is contiguous (its elements are together).
2.- Each pointer points to a contiguous array. However, each array of integers are not contiguous with each other, so there will be gaps around them.
We could visualize the heap in this way (click on the image to see it better):
In the image we can observe three things:
1.- Each array is actually like a kind of memory block.
2.- The elements of each block are contiguous.
3.- The memory blocks (or the arrays ) are not contiguous with each other, there are gaps around them.
Understanding how the two- dimensional array is reflected in memory, we could answer these questions:
You are all correct. The rows are like the array of pointers and each array that the pointer points to is like the columns and that's how you create a kind of "array".
And yes, through the pointers is how you can access each of those arrays. You basically already had the answer.
Yes you are correct. A pointer will simply contain the memory address of the first element of the array . With this saved address, an offset is added to be able to reach the memory address that you want to read or write.
No. In C, only character arrays need to end with the null character and this is because in order to traverse the entire array you need to have a beginning and an end (the null character will indicate the end).
This example shows how it works:
Two things happen here:
1.- The function
malloc
makes a call to the operating system so that it assigns to the current process (that is, to the program that is being executed) a block of 24 bytes (5 * sizeof(int)
).2.- When the system allocates the memory, the function will
malloc
return the base address of said block and in this way, by means of the pointerp
it will be possible to access any position of the reserved block.No. The compiler is not in charge of allocating dynamic memory, but functions like
malloc
,calloc
orrealloc
.If there is no memory available, these functions will return
NULL
.