【问题标题】:C language Array modification with Malloc用 Malloc 修改 C 语言数组
【发布时间】:2017-09-25 01:31:31
【问题描述】:
void helperWithoutMalloc(int *arr) {
arr[0] = 18;
arr[1] = 21;
arr[2] = 23;
}

int main() {
int *data;
helperWithoutMalloc(data);

printf("%d\n", data[0]);
return 0;
}

上述方法通过方法helperWithoutMalloc()成功修改了data的值;但是,当应用 malloc 方法时;类似的方式不起作用。数据数组中的三个值仍然为零

void helperNotWorking(int *arr) {
arr = malloc(sizeof(int)*3);
arr[0] = 18;
arr[1] = 21;
arr[2] = 23;
}
int main() {
int *data;
helperNotWorking(data);

printf("%d\n", data[0]);
return 0;
}

我只是想知道当执行 arr = malloc(sizeof(int)*3) 行时会发生什么;并使两个代码如此不同?

主要的困惑是:第一个代码不管它的错误,仍然可以修改数组元素,而第二个代码,不能修改数组元素;因为这两个函数都传递了数组的地址;我们通过地址来操作数组元素

【问题讨论】:

  • 您正在函数内部执行 malloc() 。数据在那里分配,但指针没有返回给调用函数。因此分配的内存会丢失(这是内存泄漏!)。要修复,请从调用函数(main)执行 malloc。此外,您很幸运,您的第一个示例有效,因为您没有为其工作分配内存。它可能会在某些平台上崩溃。
  • @TheGreatContini 你是这个意思吗?当调用 malloc 时,我实际上成功地修改了 helperNotWorking(); 中的数组;但因为它不返回指针;所以一旦我离开了 helperNotWorking(),我就无法访问存储在堆中的修改后的值?
  • @ElleryL 正确!
  • 这些都是未定义的行为
  • 这段代码都不正确。第一个版本正在写入未初始化的指针。有时它可能会“工作”,但它会破坏您的运行时环境,并且可能会在未来导致明显的问题。第二个版本分配一个数组,写入它,然后有效地丢弃指针。为什么不返回指针以便调用者可见?

标签: c


【解决方案1】:

C 中的任何数据结构与任何其他语言中的任何数据结构都必须提供一个可以保存其数据的内存区域。在您的第一个示例中,您没有这样做。 “数据”指针不指向任何内存并被初始化。它偶然起作用,您只是使您的程序在某处写入数据,而该数据恰好是可写的。您需要类似以下内容:

int main() {
   int data[3]; // allocate an array for data
   helperWithoutMalloc(data);

在上面的例子中,内存是由 3 个元素的 C 数组提供的。

您可以以类似的方式使用 malloc:

int main() {
   int *data = malloc(sizeof(int) * 3);
   helperWithoutMalloc(data);

请注意,数据空间是在调用函数并传递给它之前分配的。该函数可以使用指针(内存地址)来访问数组元素。

在您的第二个示例中,您犯了一个不同的错误。您分配了空间,但您将指针分配给了函数的参数。您案例中的指针按值传递给您的函数,因此它是单向的。您可以将其传递给函数,但不能向后传递。它在函数内部运行良好,但没有更新“数据”,因此从函数返回后您无法访问这些值。有几种方法可以解决它。 IE。你可以从函数中返回你的指针:

int *helper() {
    int *arr = malloc(sizeof(int)*3);
    ...
    return arr;
}
int main() {
    int *data = helper();
    ...

或者您可以使用指向指针的指针传递给函数:

 void helper(int **arr) {
    *arr = malloc(...)
    (*arr)[0] = 0;
    ...
 }

 int main () {
    int *data;
    helper(&data);

【讨论】:

    【解决方案2】:

    在我看来,正确的做法应该是

    void NoMalloc(int *arr) {
        arr[0] = 18;
        arr[1] = 21;
        arr[2] = 23;
    }
    int main() {
        int *data = (int *)malloc(sizeof(int) * 3);;
        NoMalloc(data);
        printf("%d\n", data[0]);
    
        free(data);
        return 0;
    }
    

    malloc 函数分配一些内存并返回一个指向该分配内存的指针。

    指针在内存中存储地址,当你定义一个未初始化的指针(比如你的第一段代码,int * data;)你不知道指针(data)指向哪里,因此访问存储在该位置的值通常会导致访问冲突,不应使用。

    与任何其他类型的 C 变量一样,指针在用作函数的参数时按值传递。所以data本身在调用helperWithoutMallochelperNotWorking后不会被修改。第二段代码不起作用,因为在调用helperNotWorking 之后,data 指针仍然是未初始化的指针。你虽然存储在data中的数字实际上存储在helperNotWorking函数中arr的修改值中,这不影响不再指向与data相同的地址。

    【讨论】:

    • 不好意思,加了free之后没有测试代码。我只是发现在发布答案之前我没有释放它,所以我没有仔细考虑。感谢您的更正。
    • 没问题,我已经看到你修好了,所以我已经删除了我的评论。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-19
    • 2011-12-04
    • 2015-04-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多