微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

传递带有参考的结构数组-分段错误

如何解决传递带有参考的结构数组-分段错误

Double.NaN

我创建了大小为#include <stdio.h> #include <stdlib.h> struct X { char surname[30]; int deg; }; void read_record(struct X** a,int size){ for (int i = 0;i < size; i++){ a[i]->deg = 0; } } int main(){ int n = 10; struct X *container = (struct X*)malloc(sizeof(struct X) * n); read_record(&container,n); } 的一维数组,然后将其通过引用传递给函数n。但是,当我执行程序时,出现了分段错误。有什么问题吗?

编辑:

下一步,我想在函数中重新分配大小为read_record的10个元素的数组。这就是为什么我要发送数组作为参考。如果我在20中这样做,那么我会写:

main

我如何在功能中做到这一点?

解决方法

container已经是一个指针,您不需要传递该指针的地址,而是:

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

struct X {
    char surname[30];
    int deg;
};

void read_record(struct X *a,size_t size)
{
    for (size_t i = 0; i < size; i++) {
        a[i].deg = 0;
    }
}

int main(void)
{
    size_t n = 10;
    struct X *container = malloc(sizeof(struct X) * n);

    read_record(container,n);
}

此外,更喜欢size_t存储分配的对象数。

Nitpick:read_record似乎不是修改记录内容的函数的好名字。

EDIT:下一步,我想在函数中重新分配10个元素的数组,大小为20(在函数中)。这就是为什么我要将该数组作为参考发送。

相同的方法,但返回重新分配的container

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

struct X {
    char surname[30];
    int deg;
};

struct X *read_record(struct X *a,size_t size)
{
    struct X *new = realloc(a,sizeof(struct X) * size);

    if (new != NULL)
    {
        for (size_t i = 0; i < size; i++) {
            new[i].deg = 0;
        }
    }
    return new;
}

int main(void)
{
    size_t n = 10;
    struct X *container = malloc(sizeof(struct X) * n);

    container = read_record(container,n * 2);
    if (container == NULL)
    {
        fprintf(stderr,"Can't read record\n");
        exit(EXIT_FAILURE);
    }
}
,

下一步,我想在函数中重新分配10个元素的数组,大小为20(在函数中)。这就是为什么我要将该数组作为参考发送。

该指针是按值传递的,因此要保存更改并使它们在函数作用域之外可用,在函数结束后,即在main中,指向该指针的指针必须是参数,且其地址为必须通过指针,您的总体评估是正确的。

但是,您的实现不正确,这是您应该执行的操作:

Live demo

void read_record(struct X **a,int size) //double pointer
{
    *a = realloc(*a,sizeof **a * (size + 10)); //reallocate memory for 20 ints

    if (*a == NULL)
    {
        perror("malloc");
    }

    for (int i = 0; i < size + 10; i++) //assing new values
    {
        (*a)[i].deg = 1;
    }
}
int main()
{
    int n = 10;
    struct X *container = malloc(sizeof *container * n); //original allocation
    //the pointer now has space for 10 ints

    if (container == NULL)
    { //check allocation errors
        perror("malloc");
    }

    for (int i = 0; i < n; i++) //assign values
    {
        container[i].deg = 0;
    }
    
    read_record(&container,n); //pass by reference
    //the pointer now has space for 20 ints
    
}

或者,您也可以返回指针,引用David Ranieri's answer

,

第一个函数参数具有指向指针类型struct X**的指针。因此,取消引用参数a会得到类型struct X*的指针。现在,您可以应用下标运算符,其产生类型为struct X的左值。

该函数定义如下

void read_record(struct X** a,int size){
    for (int i=0;i<size;i++){
        ( *a )[i].deg = 0;
    }
}

或者这句话

( *a )[i].deg = 0;

可以代替此声明

a[0][i].deg = 0;

另一方面,将第一个参数声明为类型struct X**毫无意义。该函数可以看起来更简单

void read_record(struct X* a,int size){
    for (int i=0;i<size;i++){
        a[i].deg = 0;
    }
}

并被称为

read_record( container,n );
,

调用read_record时,您将指针指向X结构数组的第一个元素。

但是在read_record内部,您将其视为指向X结构的指针数组的第一个元素的指针(即,指向X的指针数组)。这里有一个细微但非常重要的区别。

如果要模拟指针变量的传递引用,则需要在read_record内对其进行解引用以获取原始指针(请记住,那时您有一个对象数组,而不是指针) :

(*a)[i].deg = 0;
,

双指针是问题。该代码应为:

void read_record(struct X* a,int size){ // Check the change
    for (int i=0;i<size;i++){
        a[i]->deg = 0;
    }
}

int main(){
    int n = 10;
    struct X *container=(struct X*)malloc(sizeof(struct X)*n);
    read_record(container,n); // Check the change
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。