c - 从内部结构到相同类型的其他结构的指针数组

标签 c arrays pointers dynamic struct

我在使用指针时遇到问题。我的程序有很多指针,其中大多数都工作正常,但我试图在结构数组内添加一个指针数组,该数组指向同一结构数组中的不同成员。这应该有点像链表,但也有数组的好处。数组需要动态分配,因为数据是一个结构体数组,里面有元素,这些结构体数组里面有元素,这些元素是基本类型的数组,每个元素的数量在运行时都是未知的。我尝试过创建静态分配的数组来保存所有数据,但最终结果是很多兆字节。

我在下面创建了一个精简的测试程序,其中仅包含我遇到困难的部分。

groups[0].sub_group[0] = groups[1]; 行中,我尝试将指针分配给 groups[1] 进入groups[0].sub_group。这确实可以编译,但会给出运行时错误“EXE_BAD_ACCESS”。我认为该行应该是 groups[0].sub_group[0] = &groups[1]; 但这甚至无法编译。

最终我想从函数内部运行它,所以我还需要能够使用指向组的指针来进行此分配,例如 (*p_groups)[0].sub_group[0] = groups [1];但这也不起作用。

如果我还可以问一个相关问题:以下之间有什么区别:

(*p_groups)[0].sub_group[0] = groups[1];

p_groups[0]->sub_group[0] = groups[1]; ?

任何帮助将不胜感激。

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

typedef struct {
    char * text;
    int data_type_count;    // count of elements in data_type_list
    char * bacnet_name;     // string of name
} pup_item_t;

typedef struct pup_group_t pup_group_t;
struct pup_group_t {
    char * title;            // Null Title indicates end of list
    pup_item_t * items;      // array of items
    int item_count;          //count of items
    pup_group_t * sub_group; // array of pointers to associated sub groups
    int sub_group_count;     // count of sub groups
};

typedef pup_group_t * pup_group_array_t;

int main(int argc, const char * argv[])
{
    pup_group_array_t groups = (pup_group_t *)malloc(sizeof(pup_group_t) * 2);
    groups[0].items = (pup_item_t *)malloc(sizeof(pup_item_t)*2);
    groups[1].items = (pup_item_t *)malloc(sizeof(pup_item_t)*2);
    pup_group_array_t * p_groups;
    p_groups = &groups;

    groups[0].items[0].text = strdup("Group 0 Text 0");
    groups[0].items[1].text = strdup("Group 0 Text 1");
    groups[1].items[0].text = strdup("Group 1 Text 0");
    groups[1].items[1].text = strdup("Group 1 Text 1");

    groups[0].sub_group[0]      = groups[1]; // <-- EXE_BAD_ACCESS (code = 1, address = 0x0)
    (*p_groups)[0].sub_group[0] = groups[1]; // <-- EXE_BAD_ACCESS (code = 1, address = 0x0)

    printf("%s \n",groups[0].items[0].text);            // prints "Group 0 Text 0"
    printf("%s \n",groups[1].items[1].text);            // prints "Group 1 Text 1"
    printf("%s \n",groups[0].sub_group->items[1].text); // <-- EXE_BAD_ACCESS (code = 1, address = 0x8)
                                                        // should print "Group 1 Text 1"
    return 0;
}

2014 年 6 月 30 日更新

您在我的示例代码中是对的,我忘记了 malloc sub_group。然而,在我的实时代码中,我没有忘记这样做。我的实时代码有几千行,太大了,无法在这里发布。我已编辑示例代码以使其更接近我的实时代码。示例代码现在可以正确编译并运行(据我所知)。但我的实时代码没有执行。

以下是更新后的示例代码:

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


typedef struct {
    char * text;
    int data_type_count;    // count of elements in data_type_list
    char * bacnet_name;     // string of name
} pup_item_t;


typedef struct pup_group_t pup_group_t;
struct pup_group_t {
    char * title;            // Null Title indicates end of list
    pup_item_t * items;      // array of items
    int item_count;          //count of items
    pup_group_t * sub_group; // array of pointers to associated sub groups
    int sub_group_count;     // count of sub groups
};

typedef pup_group_t * pup_group_array_t;

void allocate_groups(pup_group_array_t * p_groups) {
    *p_groups = (pup_group_t *)malloc(sizeof(pup_group_t) * 2);
    p_groups[0]->items = (pup_item_t *)malloc(sizeof(pup_item_t) *2 );
    p_groups[1]->items = (pup_item_t *)malloc(sizeof(pup_item_t) *2 );
    p_groups[0]->sub_group = (pup_group_t *)malloc(sizeof(pup_group_t)* 2);
}

void assign_groups(pup_group_array_t * p_groups) {
    p_groups[0]->items[0].text = strdup("Group 0 Text 0");
    p_groups[0]->items[1].text = strdup("Group 0 Text 1");
    p_groups[1]->items[0].text = strdup("Group 1 Text 0");
    p_groups[1]->items[1].text = strdup("Group 1 Text 1");
    p_groups[0]->sub_group[0] = *p_groups[1];
}

void print_groups(pup_group_array_t * p_groups) {
    printf("%s \n",p_groups[0]->items[0].text);             // prints "Group 0 Text 0"
    printf("%s \n",p_groups[1]->items[1].text);             // prints "Group 1 Text 1"
    printf("%s \n",p_groups[0]->sub_group[0].items[1].text);// prints "Group 1 Text 1"
}

int main(int argc, const char * argv[])
{
    pup_group_array_t groups = NULL;

    allocate_groups(&groups);
    assign_groups(&groups);
    print_groups(&groups);

    return 0;
}

这是我的实时代码在运行时崩溃的部分:

int allocate_groups_array(char * filename, pup_group_array_t * p_groups, int * p_bacnet_count) {
    int i, size;
    int item[MAX_GROUPS_PER_FILE] = {0};
    int levels[MAX_GROUPS_PER_FILE] = {0};

    int count = scan_pup_file("ct9-103.pup", item, levels, p_bacnet_count);

    *p_groups = (pup_group_t *)malloc(sizeof(pup_group_t)*(count+1));
    for (i = 0; i <= count; i++) {
        size = sizeof(pup_item_t) * (item[i]);
        p_groups[i]->items = (pup_item_t *)malloc(size); // EXC_BAD_ACCESS (code=1, address = 0x18)
        printf("group %d is level %d has %d items with size of %d \n",i,levels[i],item[i], size);
    }

    assign_sub_groups (p_groups, count, item, levels);

    return count;
}

尺寸和其他变量的值是正确的。但是 malloc p_groups[i]->items = (pup_item_t *)malloc(size); 返回 EXC_BAD_ACCESS。我做错了什么?

** 2014 年 6 月 30 日下午更新 **

这是有人帮助我的工作版本:

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


typedef struct {
    char * text;
    int data_type_count;    // count of elements in data_type_list
    char * bacnet_name;     // string of name
} pup_item_t;


typedef struct pup_group_t pup_group_t;
struct pup_group_t {
    char * title;            // Null Title indicates end of list
    pup_item_t * items;      // array of items
    int item_count;          //count of items
    pup_group_t * sub_group; // array of pointers to associated sub groups
    int sub_group_count;     // count of sub groups
};

//typedef pup_group_t * pup_group_array_t;

pup_group_t * allocate_groups() {
    pup_group_t * p_groups = (pup_group_t *)calloc(sizeof(pup_group_t) , 201);
    p_groups[0].items = (pup_item_t *)malloc(sizeof(pup_item_t) *201 );
    p_groups[1].items = (pup_item_t *)malloc(sizeof(pup_item_t) *201 );
    p_groups[200].items = (pup_item_t *)malloc(sizeof(pup_item_t) *201 );
    p_groups[0].sub_group = (pup_group_t *)malloc(sizeof(pup_group_t *)* 201);
    return p_groups;
}

void assign_groups(pup_group_t * p_groups) {
    p_groups[0].items[0].text = "Group 0 Text 0";
    p_groups[200].items[0].text = "Group 200 Text 1";
    p_groups[1].items[200].text = "Group 1 Text 200";
    p_groups[1].items[200].text = "Group 1 Text 200";
    p_groups[200].items[200].text = "Group 200 Text 200";
    p_groups[0].sub_group[0] = p_groups[200];
}

void print_groups(pup_group_t * p_groups) {
    printf("%s \n",p_groups[0].items[0].text);                // prints "Group 0 Text 0"
    printf("%s \n",p_groups[200].items[0].text);              // prints "Group 200 Text 1"
    printf("%s \n",p_groups[0].sub_group[0].items[200].text); // prints "Group 200 Text 200"

}

int main(int argc, const char * argv[])
{
    pup_group_t * groups = allocate_groups();

    assign_groups(groups);
    print_groups(groups);

    return 0;
}

最佳答案

您尚未为 sub_group 成员变量分配任何存储空间。您还需要对其进行malloc

编辑更新的代码:对于真实的代码,我担心可能更难诊断。

看看你是否可以访问items成员,哦,等一下。 p_groups 是一个隐藏指针,因此您有一个双指针。它是一个指向数组的指针。所以不应该是:

(*p_groups)[i].items = ...

?我认为你可能会浪费你的内存,并且可能是 malloc 本身找不到它的元数据。您还可以放弃对 malloc 的强制转换,这在 C 中是不必要的。


If I may also ask a related question: What is the difference between:

(*p_groups)[0].sub_group[0] = groups[1]; and

p_groups[0]->sub_group[0] = groups[1]; ?

是的。我注意到你已经怀疑过类似的事情。不同之处在于第一行访问指向数组的指针,第二行访问指针数组。它们都是双间接,但它们将数组放置在不同的位置。

如果我们将第二个表达式重写为类似的括号形式,会更容易看出,

(*p_groups[0]).sub_groups[0] = groups[1];

并且后缀运算符首先应用,因此与此等效。

(*(p_groups[0])).sub_groups[0] = groups[1];

小测试可能会产生误导,因为索引 0 可以工作。 *E == *(E+0) == E[0]。而其他“小”指数可能不会超出范围而造成严重麻烦。但会发生一些奇怪的事情,你可能已经经历过。更改一行可以修复某些内容,即使更改实际上不应改变任何内容,诸如此类,这就是垃圾内存所做的事情。

如果你能原谅一点 ASCII 艺术,

[ -> ]
[ -> ]
[ -> ]
[ -> ]

-> [ ]
   [ ]
   [ ]
   [ ]

关于c - 从内部结构到相同类型的其他结构的指针数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24482090/

相关文章:

c - 我该如何修复我的代码?我认为问题是第一个scanf?

java - 是否可以在验证后将 input.next 作为可变长度参数列表中的参数直接传递给方法? <在java中>

c - 为什么会出现段错误?

c - 操纵指向任意位置的指针

c - 打印长度为 N 的所有二进制数

c - 如何计算字符串中字符的频率

从 getopt 转换参数

javascript - 检查具有索引的对象是否在数组中

c - 我的 for 循环出了什么问题?

将 char[][] 转换为 char** 会导致段错误?