使用指向结构数组的指针不会返回完整的数组

Posted

技术标签:

【中文标题】使用指向结构数组的指针不会返回完整的数组【英文标题】:Using a pointer to an array of structs does not return the complete array 【发布时间】:2021-11-30 10:45:11 【问题描述】:

我有一个主程序,它应该通过调用函数来加载数据(结构数组,未定义大小)、正确的数据,然后继续处理它。

以下是我正在尝试做的一个小例子。函数loadData接收指向主指针的指针,从而可以通过malloc为主指针分配一部分内存。数据在loadData 函数中加载和打印。但是当它返回 main 时,它只显示结构数组的第一项的正确内容。第二项是垃圾。

#include <stdio.h>
#include <stdlib.h>

typedef struct
 
    int dni;
    char cat;
    int weight;
 boxers;

void loadData(boxers *(*xbox), int *xcount)

    printf("How many boxers? ");
    scanf("%d", xcount);

    *xbox = (boxers *) malloc(sizeof(boxers) * (*xcount));

    for (int i = 0; i < (*xcount); i++)
    
        printf("Provide the DNI for boxer number %d: ", i);
        scanf("%d", &xbox[i]->dni);
        printf("Provide the Category for boxer number %d: ", i);
        scanf(" %c", &xbox[i]->cat);
        printf("Provide the Weight for boxer number %d: ", i);
        scanf("%d", &xbox[i]->weight);
    

    // First print the result of data loading
    for (int i = 0; i < *xcount; i++)
    
        printf("DNI for boxer number %d, is: %d \n", i, xbox[i]->dni);
        printf("Category for boxer number %d, is: %c \n", i, xbox[i]->cat);
        printf("Weight for boxer number %d, is: %d \n", i, xbox[i]->weight);
    



int main()

    boxers *box;
    int count;

    loadData(&box, &count);

    // Second print the result of data loading
    printf("\n\n");
    for (int i = 0; i < count; i++)
    
        printf("DNI for boxer number %d, is: %d \n", i, box[i].dni);
        printf("Category for boxer number %d, is: %c \n", i, box[i].cat);
        printf("Weight for boxer number %d, is: %d \n", i, box[i].weight);
    

    free(box);
    
    return 0;

控制台输出如下:

How many boxers? 2
Provide the DNI for boxer number 0: 123
Provide the Category for boxer number 0: A
Provide the Weight for boxer number 0: 45
Provide the DNI for boxer number 1: 789
Provide the Category for boxer number 1: B
Provide the Weight for boxer number 1: 56

DNI for boxer number 0, is: 123
Category for boxer number 0, is: A
Weight for boxer number 0, is: 45
DNI for boxer number 1, is: 789
Category for boxer number 1, is: B
Weight for boxer number 1, is: 56


DNI for boxer number 0, is: 123
Category for boxer number 0, is: A
Weight for boxer number 0, is: 45
DNI for boxer number 1, is: 7471203
Category for boxer number 1, is: x
Weight for boxer number 1, is: 7536756

【问题讨论】:

【参考方案1】:

&amp;xbox[i]-&gt;dni 是错误的。来自malloc 的返回值被分配给*xbox,所以*xbox 指向内存,xbox 指向那个指针。

所以内存在*xbox。第一个结构是**xbox 或等价的(*xbox)[0]。下一个结构是(*xbox)[1],以此类推。因此,对于索引为i 的结构,您需要(*xbox)[i]。然后,因为这是一个结构,而不是指向它的指针,所以你需要.dni,而不是-&gt;dni。所以那个成员是(*xbox)[i].dni。那么它的地址就是&amp;(*xbox)[i].dni

相反,由于xbox 是一个指向指针的指针,那么xbox[0] 就是那个指针,xbox[1] 就是那个指针。但是在那之后没有指针; xbox 只指向一个指针。所以xbox[i] 是错误的。

例程中的其他成员引用也需要进行相同的更改。

为了避免这个容易犯的错误,在传递指向指针的例程中,可以定义一个本地指针以使引用更容易:

void loadData(boxers **xbox, int *xcount)

    …
    boxers *p = *xbox = malloc(xcount * sizeof *p);
    …
        scanf("%d", &p[i]->dni);
    …

【讨论】:

非常感谢您的回答。你和弗拉德的都指出了原始代码的正确问题。很清楚,现在我明白我对指针指针的解释出了什么问题。【参考方案2】:

这些作业

for (int i = 0; i < (*xcount); i++)

    printf("Provide the DNI for boxer number %d: ", i);
    scanf("%d", &xbox[i]->dni);
    printf("Provide the Category for boxer number %d: ", i);
    scanf(" %c", &xbox[i]->cat);
    printf("Provide the Weight for boxer number %d: ", i);
    scanf("%d", &xbox[i]->weight);

不正确。你必须写

for (int i = 0; i < (*xcount); i++)

    printf("Provide the DNI for boxer number %d: ", i);
    scanf("%d", &( *xbox )[i].dni);
    printf("Provide the Category for boxer number %d: ", i);
    scanf(" %c", &( *xbox )[i].cat);
    printf("Provide the Weight for boxer number %d: ", i);
    scanf("%d", &( *xbox )[i].weight);

然后

for (int i = 0; i < *xcount; i++)

    printf("DNI for boxer number %d, is: %d \n", i, ( *xbox )[i].dni);
    printf("Category for boxer number %d, is: %c \n", i, ( *xbox )[i].cat);
    printf("Weight for boxer number %d, is: %d \n", i, ( *xbox )[i].weight);

比较上面的循环和main中的这个循环

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

    printf("DNI for boxer number %d, is: %d \n", i, box[i].dni);
    printf("Category for boxer number %d, is: %c \n", i, box[i].cat);
    printf("Weight for boxer number %d, is: %d \n", i, box[i].weight);

不同之处在于,在 main 中,指针 box 的类型为 boxers *,而在函数中,指针 xbox 的类型为 boxers **。因此,您首先需要取消引用函数中的指针,例如 ( *xbox ),然后像在 main 中一样应用下标运算符,例如 ( *xbox )[i].weight

【讨论】:

非常感谢您的回答。您和 Eric 都指出了原始代码的正确问题。很清楚,现在我明白我对指针指针的解释出了什么问题。

以上是关于使用指向结构数组的指针不会返回完整的数组的主要内容,如果未能解决你的问题,请参考以下文章

C++指针问题,请问如何定义一个返回值为结构体指针数组的函数?

C 语言二级指针案例 ( 字符串切割 | 返回 自定义二级指针 作为结果 )

返回指向结构的指针并访问其字段 C++

C ++从函数返回指向数组的指针的正确方法

C 语言结构体 ( 结构体 数组 作为函数参数 | 数组 在 堆内存创建 )

C 语言二级指针案例 ( 字符串切割 | 返回 自定义二级指针 作为结果 | 每个 一级指针 指向不同大小内存 | 精准分配每个 一级指针 指向的内存大小 )