在函数内动态分配结构数组

Posted

技术标签:

【中文标题】在函数内动态分配结构数组【英文标题】:Dynamically allocating an array of struct inside a function 【发布时间】:2017-01-12 14:35:19 【问题描述】:

我无法理解我的 c 实现有什么问题:在函数内部动态分配结构数组以在其他函数中使用。

问题是我的 .exe 在读取第一个结构后停止工作(读取正确)。

结构:

struct student

    char name1[30], name2[30];
    float grade;
;

功能:

void read(int *n, struct student **a)

    if(scanf(" %d", n) == 1)
    
        int i;
        *a=(struct student*)malloc((*n)*sizeof(struct student*));
        for(i=0; i<*n; i++)
            scanf("%29s %29s %f",(*a)[i].name1, (*a)[i].name2, &(*a)[i].grade);
            //it stops working right after this line is executed
    

主要:

int main()

    int n;
    struct student *a;
    read(&n, &a);
    return 0;

警告:

format '%s' expects argument of type 'char *', but argument 2 has type 'char (*)[30]' [-Wformat=]|

format '%s' expects argument of type 'char *', but argument 3 has type 'char (*)[30]' [-Wformat=]|

使用 a+i 代替 a[i] 不会改变任何东西。我知道 &(*a) 表示 a,但我想让一切尽可能清楚。我觉得我的动态分配明显有问题,我错过了。我在这里阅读了很多问题,但似乎没有任何问题可以解决我的问题。感谢您的宝贵时间!

编辑 1:我将代码更改为建议:

scanf("%29s %29s %f", a[i].name1, a[i].name2, a[i].grade);

现在我得到了下面的错误。

错误:

错误:在非结构或联合的情况下请求成员“name1”

编辑2:所以,行:

 scanf("%29s %29s %f",*a[i].name1, *a[i].name2, *a[i].grade);

给出错误:

在非结构或联合的情况下请求成员“name1”

还有一行:

scanf("%29s %29s %f",(*a)[i].name1, (*a)[i].name2, (*a)[i].grade);

崩溃。

编辑 3:

scanf("%29s %29s %f", (*a)[i].name1, (*a)[i].name2, &(*a)[i].grade);

有效。

【问题讨论】:

这是一个关于operator precedence 的问题。使用您的代码,表达式 *a[i] 等于 *(a[i]),这是不正确的。 这是第一次,希望是最后一次,我见过有人写 &(*a)。 这个:scanf("%d",&amp;(*n)); 太吓人了,当然应该是if(scanf(" %d", n) == 1),不用解引用再取地址,你有开头的地址 . I/O 也可能失败,%d 之前的空间非常好。 ((*a)[i]).name2(附加括号:@Someprogrammerdude 是对的)是一个 char 数组,当用作函数参数时,它被调整为指向其第一个元素的指针。取数组的地址不会改变数值(因为数组的第一个元素的地址和数组本身的地址都是第一个元素的第一个字节的地址),但它会改变 type,指向数组的指针。只需省略地址运算符,您将传递一个指向name2 中第一个字符的指针,这就是您想要的。 @Someprogrammerdude 虽然您的评论实际上是正确的,但这不是编译器评论的原因,而是会在运行时崩溃。毕竟,索引是解引用的一种形式,而这两个必要的解引用发生的顺序在语法上是不相关的。编辑:哦,我看到 OP 也在询问运行时崩溃。没关系... 【参考方案1】:

这里

*a=(struct student*)malloc((*n)*sizeof(struct student*));
                                                   ^^^^^

您为*n 分配空间指针struct student,但您似乎真的想为*n struct student 分配空间。

看来你想要:

*a=malloc((*n)*sizeof(struct student));

还要注意*a[i]*(a[i]) 相同,但您可能需要(*a)[i]。所以你需要这样的东西:

scanf("%29s %29s %f", (*a)[i].name1, (*a)[i].name2, &(*a)[i].grade);

注意(*a)[i].grade前面需要&amp;,但其他两个地方不需要,因为另外两个是数组。

@unwind 在评论中提到:scanf 是错误的

这个

scanf("%d",&(*n));

应该是

scanf("%d", n);

然后你还应该检查返回值,比如

if (scanf("%d", n) != 1)

    // Add error handling here
    ....

【讨论】:

以上是关于在函数内动态分配结构数组的主要内容,如果未能解决你的问题,请参考以下文章

C ++在函数内部分配动态数组[关闭]

C语言,怎么为动态结构体数组分配内存

栈的动态内存分配数组

在字符串和结构数组中查找动态内存分配错误

C++ 动态内存分配与结构中的数组

C中结构内的字符串数组,无需分配