【问题标题】:Passing a pointer to an array of structs to a function for malloc将指向结构数组的指针传递给 malloc 的函数
【发布时间】:2019-09-26 03:18:12
【问题描述】:

我环顾四周,找到了有关如何为带有指针表示法的二维数组正确分配内存的答案,并且我发现了如何正确地将二维指针数组传递给函数,但我似乎无法结合两个步骤。

所以从逻辑上讲,我想要做的是分配一个指向结构的指针数组。似乎失败的是尝试分配内存

到目前为止我的代码:

typedef struct {
int tax, savings;
float salary;
} employee;

int readRecordFile(char* filename, Record*** array);

int main(void) {

employee** array;
int size;
char* file = "money.csv";
size = readRecordFile(file, &array);

FILE* fptr;
fptr = fopen(file, "r");


//Read the file into the the array 
for (int i = 0; i < size; i++) {
    fscanf(fptr, "%d,%d,%f", array[i]->tax, array[i]->savings, array[i]->salary);
}
fclose(fptr);


for (int i = 0; i < size; i++) {
    printf("%d, %d, %f\n", array[i]->tax, array[i]->savings, array[i]->salary);
}
return 0;
}

int readRecordFile(char* filename, employee*** array) {
//Function to open the file, malloc and initialize 2d arrays

//Open the file
FILE* fileptr;
fileptr = fopen(filename, "r");
if (fileptr == NULL) {
    printf("Failed to open file");
    exit(-1);
}

//Read first line of file (the size) and store to an int
int n;
fscanf(fileptr, "%d", &n);

//Initial malloc for the array of pointers
**array = malloc(n * sizeof(employee*)); //This is the line that throws the exception

//Malloc for each pointer in the array of pointers
for (int i = 0; i < n; i++) {
    *(array+i) = malloc(sizeof(employee));
}


//Close the file and return the size of the file
fclose(fileptr);

return n;
}

我尝试在函数中构建一个单独的结构指针,然后将常规指针设置为它

    //Initial malloc for the array of pointers
employee **tester = malloc(n * sizeof(employee*));

//Malloc for each pointer in the array of pointers
for (int i = 0; i < n; i++) {
    *(tester+i) = malloc(sizeof(employee));
}

array = tester;

此方法似乎可以修复 malloc 问题,但 main 中的数据打印失败。

【问题讨论】:

标签: c


【解决方案1】:

您正在正确分配结构的二维数组。

但你只是读入一个一维结构数组。 (例如array[i]-&gt;tax

要读取 struct 的 2D 数组,您需要 2 个 for 循环

for (int i = 0; i < size; i++) {
    for (int j=0; j< size; j++) { // in your case you have a size*size array, 
        fscanf(fptr, "%d,%d,%f", array[i][j]->tax, array[i][j]->savings, array[i][j]->salary);
     }
}

您需要决定是需要一维数组还是二维数组。

【讨论】:

    【解决方案2】:

    employee **array; 不是数组,它是单指针。 (指向员工的指针)。

    调用时size的值是多少:

    for (int i = 0; i < size; i++) 
    

    size 是不确定的(它的值是程序启动时内存中发生的任何垃圾值)。您调用 Undefined Behavior 试图访问不确定的值。 size必须在使用前设置(所有变量都一样)

    此时,array 是一个未初始化的指针,试图访问一个不确定的地址同样糟糕。 (请记住,指针只是一个普通变量,它保存其他东西的地址作为它的值)。由于array 持有的地址尚未分配,也没有为任何employee 结构分配存储空间,因此您不能这样做:

    fscanf(fptr, "%d,%d,%f", array[i]->tax, array[i]->savings, array[i]->salary);
    

    在你使用array之前,你必须:

    1. 分配一定数量的指针并将持有已分配指针的内存块的开头分配给array,然后
    2. 为每个结构分配存储空间,并将每个存储结构块的起始地址分配给指针array[i] 之一。

    例如,最初声明 64 个指针,您可以这样做:

    array = malloc (64 * sizeof *array);
    

    注意:使用取消引用的指针(sizeof *array)总是会产生正确的类型大小,而不是尝试匹配类型,例如sizeof (employee*)

    始终验证每个分配,例如

    if (array == NULL) {            /* if the pointer returned by malloc is NULL */
        perror ("malloc-array");    /* issue diagnostic (perror is simple) */
        exit (EXIT_FAILURE);        /* handle error */
    }
    

    现在如何为每个结构分配? (一样的方法)。但是,一种更容易读取、分配和验证的方法是使用具有自动存储功能的临时结构并读取和填充临时结构。如果您的读取成功,则为您的结构分配存储空间,将该内存块的起始地址分配给array[i],然后将临时结构的内容分配给您的新内存块。例如(在你修复 size 初始化之后):

    for (int i = 0; i < size; i++) {
        employee tmp = { .tax = 0 };    /* declare temporary struct, initialized zero */
        /* read values into temporary struct / VALIDATE every input */
        if (fscanf (fptr, "%d,%d,%f", tmp.tax, tmp.savings, tmp.salary) == 3) {
            array[i] = malloc (sizeof *array[i]);   /* allocate for struct */
            if (!array[i]) {                        /* validate allocation */
                perror ("malloc-array[i]");
                exit (EXIT_FAILURE); 
            }
            array[i] = tmp;             /* assign temp struct to allocated block */
        }
    }
    

    现在,当您使用完“数组”后,不要忘记释放分配的内存。例如,假设您有效填写了size,那么您可以这样做:

    for (int i = 0; i < size; i++)
        free (array[i]);            /* free each allocated struct */
    free (array);                   /* free pointers */
    

    您发布的代码中可能还有其他错误(它的顺序有些混乱),但这些是您面临的最直接的错误。进行更改并进一步测试。确保所有变量在使用前都已正确初始化。确保您已为将要使用的每个指针分配存储空间,然后为每个结构分配存储空间的地址,并将该结构存储空间的地址分配给您分配的指针之一。如果您遇到另一个障碍,请编辑此问题(或者最好提出一个新问题),并注明您遇到的具体问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-02
      相关资源
      最近更新 更多