指向结构的指针让人头疼。 。

时间:2011-03-22 17:29:52

标签: c

我不知道如何解释这个但是这段代码可以完美编译但是当你运行它时,SIGSEV。 请问,任何人都可以准确地告诉我哪里出错了吗? 事实上,我希望能够通过索引访问元素,如下所示,同时能够使用struct。

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

/* This is a struct describing properties of an element */
struct element{
    int age;
    char* name;
};

/* This struct contains a pointer to a pointer on a element "struct element" */
struct person{
    struct element** p;
    int id;
};

/* Thus function initializes a struct person by allocation memory for it */
struct person* init(int size)
{
    struct person* sample = (struct person* )malloc(size*sizeof(struct person));
    sample->p = NULL;
    sample->id = 0;
    return sample;
}

/* use this function to insert a new element in the struct */
void insert(struct person* sample, char* _name, int _age)
{
    sample->p[sample->id]->name = _name; /* the program crashes here  according to the debugger , but why?? */
    sample->p[sample->id]->age = _age;  /* of course, this will cause trouble too because it has the same construct as the previous one */
    sample->id++;
}


/* main entry */
int main()
{
    struct person* student = init(10); /* Allocating space for 10 students */
    insert(student, "kido", 8);
    printf("Your name is %s and your age is %d", student->p[0]->name, student->p[0]->age); /* we can't write student->p->name */
    return 0;
}

5 个答案:

答案 0 :(得分:5)

问题出在您在问题中标记的代码行的insert方法

sample->p[sample->id]->name = _name;

您的程序中没有任何地方为p结构内的person数组分配内存。因此,此值始终为NULL。尝试分配此值将正确导致程序崩溃。

要解决此问题,您需要确保p数组足够大,以容纳表达式sample->id提供的索引。实现此目的的最佳方法是使用realloc函数并向person添加字段以存储p数组的大小

这是一个快速的样本。注意:为了简单起见,省略了错误检查和0内存初始化。

struct person{
    struct element** p;
    size_t length;
    int id;
};

void insert(struct person* sample, char* _name, int _age)
{
  if (sample->id >= sample->length) {
    sample->p = realloc(sample->p, sizeof(element*) * sample->id);
  }
  ...
}

虽然名称和年龄始终通过sample->id字段编入索引,但看起来确实很奇怪。这表明它总是放在同一个位置,在这种情况下不需要数组。你能详细说明它应该如何运作吗?

答案 1 :(得分:0)

在init()函数中设置sample->p = NULL。在您的insert()函数中,您尝试取消引用 - &gt; p成员sample->p[sample->id]->name。由于您没有将 - &gt; p指向任何存储,因此您无法取消引用它。

答案 2 :(得分:0)

Starting program: /home/nathan/c/seg 

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400597 in insert (sample=0x601010, _name=0x400730 "kido", _age=8)
    at seg.c:28
28          sample->p[sample->id]->name = _name; /* the program craches here  according to the debugger , but why?? */
(gdb) backtrace
#0  0x0000000000400597 in insert (sample=0x601010, _name=0x400730 "kido", 
    _age=8) at seg.c:28
#1  0x0000000000400601 in main () at seg.c:38
(gdb) p sample->id
$1 = 0
(gdb) p sample->p
$2 = (struct element **) 0x0

sample->p未正确初始化。如果您查看init,它确实已初始化为NULL。因此sample->p[anything]取消引用空指针,导致段错误。

答案 3 :(得分:0)

当你调用init()函数时,你为许多person结构分配内存,并将第一个结构的'p'指针设置为NULL。

然后你尝试写'p'指向的内存。当然,这仍然是NULL。

鉴于您的意见,我不认为init()正在做您想要它做的事情。它为人员结构数组分配空间,而不是具有“p”数组的人。另外,为什么双指针?

重新检查你的设计:)我通常用白板,铅笔和纸做,用我的“物品”框和箭头作为我的指针。它将澄清您的想法,并可能在他们达到代码之前向您显示错误。

答案 4 :(得分:0)

struct person* init(int size)
{
    struct person* sample = (struct person* )malloc(size*sizeof(struct person));
    sample->p = NULL; // p is a pointer to a pointer which is initialized to NULL
                      // So, it cannot be dereferenced with out pointing to a valid
                      // memory location.

    // sample -> p = (struct person**) malloc( sizeof(struct *person) );
    // sample[p] = (struct(person*)) malloc( sizeof(struct person) );

    // struct** -> struct* -> struct

    sample->id = 0;
    return sample;
}

现在,这两个陈述是有效的 -

sample->p[sample->id]->name = _name;
sample->p[sample->id]->age = _age;