andypf
andypf

Reputation: 197

Setting Dynamic arrays equal to eachother in C

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

Answers (3)

dbush
dbush

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

R Sahu
R Sahu

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

ameyCU
ameyCU

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

Related Questions