在C中设置动态数组等于彼此

时间:2015-10-22 05:58:13

标签: c arrays pointers

int staticArrayA[10];
int staticArrayB[10];
int *dynamicArrayA = (int *)malloc(sizeof(int) * 10);
int *dynamicArrayB = (int *)malloc(sizeof(int) * 10);

根据我的理解,staticArrayA的值是指向数组中第一个元素的指针,但是表示此基址的指针的行为类似于const指针并且无法更改,在这种情况下,有意义的是你不能设置:

staticArrayA = staticArrayB;

但是动态数组呢?如果它们都只是指向内存中连续字节块的指针,那么为什么不能将它们设置为相等呢?

dynamicArrayA = dynamicArrayB;

看起来dynamicArrayA指向的地址现在与dynamicArrayB指向的地址相同。请给我一些见解。也许我错了,但这就是我想要做的事情:

/* 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;
}

我确信有更简单,更优雅的方式来编写函数,我知道我可以将nuArray的所有元素复制到数组中,然后使用realloc()来减小大小,但是,我只是希望有人能够对动态数组的本质有所了解,并解释一些这种行为并告诉我为什么赋值不起作用,或者是否存在它的作用。此外,我可以让函数返回一个int *并将array =设置为此函数调用,但是为什么我不能在函数内部执行此操作?感谢您的时间和任何帮助。

3 个答案:

答案 0 :(得分:2)

  

如果它们都只是指向内存中连续字节块的指针,那么为什么不能将它们设置为彼此相等?

当然可以。你只需要了解其后果。

int *dynamicArrayA = (int *)malloc(sizeof(int) * 10);
int *dynamicArrayB = dynamicArrayA;

现在dynamicArrayBdynamicArrayA指向相同的内存。您更改了指向的值,通过其他指针也可以看到更改。

dynamicArrayB[0] = 10; // dynamicArrayA[0] is 10.
dynamicArrayA[5] = 15; // dynamicArrayB[5] is 15.

如果这是你的目标,你可以毫无问题地做到这一点。

更新,以回应OP的评论

该行

array = nuArray; //This doesn't seem to work

array中本地更改compressArray的值。这不会改变arraymain的值。

您必须采用不同的方法将nuArray返回main

问题的一个解决方案是将compressArray的返回类型从void更改为char*并从函数返回nuArray

答案 1 :(得分:1)

int *dynamicArrayA = (int *)malloc(sizeof(int) * 10);
int *dynamicArrayB = (int *)malloc(sizeof(int) * 10);

如果你这样做(哪个可能的话) -

dynamicArrayA = dynamicArrayB;  //you want this then don't allocate memory to dynamicArrayA

现在,dynamicArrayA不会指向malloc先前为其分配的内存,因此您无法free该内存块。因此,可能导致内存泄漏。

您可以使用memcpy执行此任务 -

/* 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);

答案 2 :(得分:0)

让我们来看看compressArray结束时实际发生的事情:

array = nuArray;

在此声明之后,array现在指向nuArray指向的相同内存。 array之前指向的内存现在可以在compressArray内访问,但array中的main仍然指向原始内存块。这是因为此块的地址是传递给compressArray的地址,而不是array变量的地址。

free(nuArray);

这释放了nuArray指向的内存。但由于array包含与nuArray相同的值,即nuArray指向的内存块的地址,现在array指向一个释放的内存块,并访问这是未定义的行为。

当函数返回时,main中array的值不变。这是因为传递了array

为了使其按预期工作,compressArray需要获取指针的地址(int **)并更改指向的内容:

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
}

然后你这样称呼它:

compressArray(&array, 10);
// print the new contents of array
free(array);    // We're done with it now, so free it