You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何C语言函数内对数组的修改无法在main函数中持久化?

问题:为何C语言函数内对数组的修改无法在main函数中持久化?

我编写了一个读取CSV文件的函数,当仅调用read_csv而不接收其返回的void**时,在main函数中打印数组值会触发段错误;但将函数返回的数组赋值给main中的array变量后则能正常运行。请问为何函数内对数组的修改无法在main函数中持久化?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
    
#define NITEMS 7
#define SIZE sizeof(Data)
#define K 5 
    
typedef struct _data
{
    int id;
    char field1[50];
    int field2;
    float field3;
}Data;
    
void ** read_csv(void **array, const char *filename){
    int capacity = 1, size = 0; 
    FILE *file = fopen(filename, "r");
    if (file == NULL) {
        printf("errore");
        return NULL;
    }
    
    Data *row;
    while (!feof(file)){ 
        row = malloc(sizeof(Data)); 
        if (row == NULL) {
            printf("Unable to allocate new row!");
            exit(EXIT_FAILURE);
        }
    
        fscanf(file,"%d,%49[^,],%d,%f\n",&row->id,&row->field1,&row->field2,&row->field3);
    
        if (size >= capacity) {
            capacity = 2 * capacity; 
            array = (void **)realloc(array, capacity * sizeof(void**));
        }
        array[size] = row;
        size++;
        printf("\n\n%d", ((Data*)array[0])->id);
    }
    fclose(file);
    return array;
}
    
int main(int argc, char const *argv[])
{
    if(argc < 3){
        printf("\n Please make sure that each file is inserted in correct way: \n  ./main first(csv)  second (ordered csv) third(k) fourth(field)\n\n");
        exit(EXIT_FAILURE);
    }
    
    void ** array = malloc(sizeof(void **));
    if(array == NULL)
        exit(EXIT_FAILURE);
    
    // read_csv(array,argv[1]) --> this don't mantain the changes
    array = read_csv(array, argv[1]);  // this yes
    
    return 0;
}

解答

核心原因是C语言的参数传递是值传递,加上realloc的内存重分配特性共同导致的:

  1. 值传递的特性:
    当你把main函数中的array指针传给read_csv时,函数会创建一个该指针的副本。函数内部对array的所有修改(比如重新赋值)都只作用于这个副本,完全不会影响main函数里的原指针。

  2. realloc的影响:
    当数组容量不足时,realloc会申请一块新的更大内存,把旧内存的数据拷贝过去,然后释放旧内存。此时函数内的array副本会被更新为新内存的地址,但main函数里的原指针仍然指向已经被释放的旧内存。

  3. 两种调用方式的差异:

    • 直接调用read_csv(array, argv[1])不接收返回值:main里的array还是旧地址,这块内存已经被realloc释放,后续访问会触发段错误。
    • 用array = read_csv(array, argv[1])接收返回值:main里的array被赋值为函数返回的新内存地址,这个地址是有效的,所以能正常访问数组内容。

如果不想用返回值的方式,也可以通过传递指针的指针(比如void ***array)来让函数修改外层指针的指向,但返回值的写法更直观易读,也是这类场景的常规做法。


内容的提问来源于stack exchange,提问作者Matteo Pagliarello

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 11:58:09