【问题标题】:Pointers to Dynamic Arrays in CC 中指向动态数组的指针
【发布时间】:2015-03-29 16:04:08
【问题描述】:

我正在尝试学习如何创建一个函数,该函数将采用动态 int 数组 (int arrayPtr = (int) malloc...) 并将其替换为另一个动态数组。这个新数组不仅具有不同的值,而且可能具有不同数量的元素。

从我的研究中,我了解到我需要将一个对我的数组指针的引用传递给这个函数,而不是指针本身 (&arrayPtr)。这意味着函数签名需要具有 int **arrayPtr 而不是 int *arrayPtr。

我觉得这对我来说很有意义;我们需要告诉arrayPtr指向内存中不同的位置,所以我们需要arrayPtr的内存地址而不是它的值(原始数组的内存地址);

我写了一个小测试程序来看看我是否理解,但我无法让它工作。使用调试,我观察到以下情况: 从函数内部, (int **arrayPtr) 不代表整个数组,而只是第一个元素。也就是说,如果我做*arrayPtr[0],我可以得到值500,但是*arrayPtr[1]是不可访问的内存。

这是我的测试程序:

#include <stdlib.h>

void replaceArray(int **arrayPtr, unsigned int arrayLength) {

    int i;
    int *tempArrayPtr;

    tempArrayPtr = (int *)malloc(sizeof(int) * arrayLength);

    for (i = 0; i < arrayLength; ++i) {
        tempArrayPtr[i] = *arrayPtr[i] * 2;
    }

    free(arrayPtr);

    arrayPtr = &tempArrayPtr;

    return;
}

int main(int argc, char **argv) {

    int i;
    int arrayLength = 2;
    int *arrayPtr;

    arrayPtr = (int*)malloc(sizeof(int) * arrayLength);
    for (i = 0; i < arrayLength; ++i) {
        arrayPtr[i] = i + 500;
    }

    replaceArray(&arrayPtr, arrayLength);

    exit(EXIT_SUCCESS);
}

该函数应该创建一个新数组,其中原始数组的每个元素的值加倍,并让调用函数中的 arrayPtr 变量引用新数组。然而,正如我所写的,当 replaceArray 函数尝试访问 *arrayPtr[1] 时,它会得到 SIGSEGV。

我意识到这个小演示程序并没有做任何需要我正在测试的行为的事情。只是为了让我通过一个简单的例子来理解这个概念。

由于这是一个很小的、微不足道的程序,我认为我接受的答案将包含此代码的完整工作版本。

【问题讨论】:

标签: c arrays pointers dynamic


【解决方案1】:

您的代码必须进行三处更改:

void replaceArray(int **arrayPtr, unsigned int arrayLength) {

    int i;
    int *tempArrayPtr;

    tempArrayPtr = malloc(sizeof(int) * arrayLength);

    for (i = 0; i < arrayLength; ++i) {
            tempArrayPtr[i] = (*arrayPtr)[i] * 2;//In this if you use the without braces it will acts array of pointers that is pointing to a array. So we have to get the value from that using that braces.
    }
    free(*arrayPtr);//<< here we have to free the memory of arrayPtr not the address of the &arrayPtr.

    *arrayPtr = tempArrayPtr; // Here you have to assign the address to that value of arrayPtr.

    return;
}

malloc的返回值不需要类型转换。

【讨论】:

    【解决方案2】:

    这两行都是错误的:

    free(arrayPtr);
    arrayPtr = &tempArrayPtr;
    

    第一行将变量的地址传递给free(),而不是实际分配数组的地址。由于变量在堆栈上而不是被分配,free() 将在此处崩溃或中止。你想做的是free(*arrayPtr):

    第二行只是将局部变量arrayPtr 设置为变量tempArrayPtr 的地址。你想做的是*arrayPtr = tempArrayPtr;

    【讨论】:

      【解决方案3】:

      请参阅下面的代码和内联 cmets。

      #include <stdlib.h>
      
      void replaceArray(int **arrayPtr, unsigned int arrayLength) {
      
          int i;
          int *tempArrayPtr;
      
          tempArrayPtr = malloc(sizeof(int) * arrayLength);  //do not cast
      
          for (i = 0; i < arrayLength; ++i) {
              tempArrayPtr[i] = (*arrayPtr)[i] * 2;
          }
      
          free(*arrayPtr);  // free the *arrayPtr, [which is `arrayPtr` from `main`]
      
          *arrayPtr = tempArrayPtr;   //copy tempArrayPtr and put it into *arrayPtr
      
          return;
      }
      
      int main(int argc, char **argv) {
      
          int i;
          int arrayLength = 2;
          int *arrayPtr;
      
          arrayPtr = malloc(sizeof(int) * arrayLength);  // do not cast
          for (i = 0; i < arrayLength; ++i) {
              arrayPtr[i] = i + 500;
          }
      
          replaceArray(&arrayPtr, arrayLength);
      
          exit(EXIT_SUCCESS);
      }
      

      【讨论】:

      • 太棒了。谢谢。第三个更改是我尝试过的,但我不知道第一个更改。我将不得不研究为什么它会这样。我很好奇你为什么说不要投射 malloc。我现在是一名学生,课程材料中的每个 malloc 示例都是强制转换的。
      • @donald 我刚出去吃午饭。我会回复你的询问。同时您可以访问我评论中的链接以获取与铸造相关的答案。
      • 这是一个非常有趣的话题。这似乎是一个持续的争论,无论是否演员。反对选角的论点有大约 4 倍的 +1,但选角的论点更加连贯。那么我不确定我在哪个营地。
      猜你喜欢
      • 1970-01-01
      • 2017-02-07
      • 1970-01-01
      • 1970-01-01
      • 2011-01-02
      • 1970-01-01
      • 2012-07-16
      • 2012-03-09
      • 1970-01-01
      相关资源
      最近更新 更多