Reputation: 197
int staticArrayA[10];
int staticArrayB[10];
int *dynamicArrayA = (int *)malloc(sizeof(int) * 10);
int *dynamicArrayB = (int *)malloc(sizeof(int) * 10);
From what I understand, the value of staticArrayA is a pointer to the 1st element in the array, however the pointer that represents this base address behaves like a const pointer and cannot be changed, in which case it makes sense that you cannot set:
staticArrayA = staticArrayB;
But what about dynamic arrays? if they are both just pointers to a contiguous block of bytes in memory, then why can't you set them equal to eachother?
dynamicArrayA = dynamicArrayB;
It seems like the address that dynamicArrayA points to would now be the same address that dynamicArrayB points to. Please give me some insight. Perhaps I am wrong, but here is what I was trying to do:
/* remove any element that is 0 from array. n is size of array */
void compressArray(int *array, int n) {
int size = n;
int index = 0;
int *nuArray = (int *)malloc(sizeof(int) * n);
assert(nuArray != NULL);
for (int i = 0; i < n; i++) {
if (array[i] != 0) {
nuArray[index] = array[i];
index++;
size--;
}
}
nuArray = realloc(nuArray, sizeof(int) * size);
assert(nuArray != NULL);
array = realloc(array, sizeof(int) * size);
assert(array != NULL);
array = nuArray; //This doesn't seem to work
free(nuArray);
}
int main(int argc, const char * argv[]) {
int *array = (int *)malloc(sizeof(int) * 10);
assert(array != NULL);
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) {
array[i] = 0;
} else {
array[i] = i;
}
}
compressArray(array, 10);
return 0;
}
I am sure that there are much simpler and more elegant ways to write the function, and i know that I can copy all the elements of nuArray into array and then use realloc() to reduce the size, however, I am just hoping someone can give some insight into the nature of dynamic arrays and explain some of this behavior and tell me why the assignment does not work, or if there are cases in which it does. Also, i could have the function return an int * and set array = to this function call and that works, however why can't i do it inside the function? Thanks for your time and for any help.
Upvotes: 0
Views: 2200
Reputation: 223872
Let's take a look at what's actually happening at the end of compressArray
:
array = nuArray;
After this statement, array
now points to the same memory that nuArray
points to. The memory that array
previously pointed to is now accessible inside of compressArray
, however array
in main
still points to the original memory block. That's because the address of this block is what was passed to compressArray
, not the address of the array
variable.
free(nuArray);
This frees the memory pointed to by nuArray
. But since array
contains the same value as nuArray
, i.e. the address of the memory block pointed to by nuArray
, now array
points to a freed block of memory, and accessing it is undefined behavior.
When the function returns, the value of array
in main is unchanged. That's because the value of array
was passed in.
For this to work as expected, compressArray
needs to take the address of a pointer (an int **
) and change what that points to:
void compressArray(int **array, int n) { // "array" is a pointer to an array
int size = n;
int index = 0;
int *nuArray = (int *)malloc(sizeof(int) * n);
assert(nuArray != NULL);
for (int i = 0; i < n; i++) {
if ((*array)[i] != 0) { // note how we're now accessing the array
nuArray[index] = (*array)[i]; // same here
index++;
size--;
}
}
nuArray = realloc(nuArray, sizeof(int) * size);
assert(nuArray != NULL);
free(*array); // We don't need the memory array pointed to anymore, so free it
*array = nuArray; // This changes "array" in main. Also, don't free nuArray,
// otherwise *array will also point to freed memory
}
Then you call it like this:
compressArray(&array, 10);
// print the new contents of array
free(array); // We're done with it now, so free it
Upvotes: 0
Reputation: 206577
if they are both just pointers to a contiguous block of bytes in memory, then why can't you set them equal to each other?
Of course you can. You just have to know the ramifications.
int *dynamicArrayA = (int *)malloc(sizeof(int) * 10);
int *dynamicArrayB = dynamicArrayA;
Now dynamicArrayB
and dynamicArrayA
point to the same memory. You change the value of what one points to, the change will be visible through other pointer too.
dynamicArrayB[0] = 10; // dynamicArrayA[0] is 10.
dynamicArrayA[5] = 15; // dynamicArrayB[5] is 15.
If that's your objective, you can do that without any problem.
Update, in response to OP's comment
The line
array = nuArray; //This doesn't seem to work
changes the value of array
locally in compressArray
. That does not change the value of array
in main
.
You'll have to come up with a different method to return nuArray
back to main
.
One solution to the problem would be to change the return type of compressArray
from void
to char*
and return nuArray
from the function.
Upvotes: 2
Reputation: 16607
int *dynamicArrayA = (int *)malloc(sizeof(int) * 10);
int *dynamicArrayB = (int *)malloc(sizeof(int) * 10);
After this if you do this ( which ofcourse is possible ) -
dynamicArrayA = dynamicArrayB; //you want this then don't allocate memory to dynamicArrayA
Now , dynamicArrayA
won't point to memory allocate by malloc
to it previously , so you won't be able to free
that memory block . Thus , can lead to memory leak.
You can use memcpy
for this task -
/* allocate memory to both dynamicArrayA and to dynamicArrayB */
for(int i=0;i<10;i++){
dynamicArrayA[i]=i+1; // store value in dynamicArrayA
}
memcpy(dynamicArrayB,dynamicArrayA,sizeof(int)*10); //copy it to dynamicArrayB
for(int i=0;i<10;i++)
printf("%d",dynamicArrayB[i]); // print values
free(dynamicArrayA);
free(dynamicArrayB);
Upvotes: 1