如何访问嵌套结构并访问要使用的内容?

时间:2017-02-20 02:18:21

标签: c struct

我试图学习如何使用嵌套结构,并且正在做一个" pthread生产者和消费者"比如说。

我已经初始化了这些:

int MAILBOX_SIZE = 10;

typedef struct Message {
        int bytes;
        void *data;
} Message;

typedef struct Mailbox {
        Message *queue;
        int in; //place to add next element in buffer
        int out; //place to remove next element in buffer
        int cnt; //number of elements in buffer
} Mailbox;

void mb_init(Mailbox *sb, int size);

现在我想创建这个初始化函数以便能够访问队列。

我的方法可能是错的,但我在想的是:

void mb_init(Mailbox *sb, int size){
        sb->queue=(Message*)malloc(sizeof(Message));
        sb->queue->bytes = size;
        printf("%i\n", sb->queue->bytes);

}

int mb_put(Mailbox *sb, Message *msg){
        //actions of the producer

}

int mb_get(Mailbox *sb, Message *msg){
        //actions of the consumer
}

我的主要(伪代码,因为我在主要方面有更多)是这样的:

int main() {
   struct Mailbox *myMailbox;
   mb_init(myMailbox, MAILBOX_SIZE);
}

我最终得到了一个"分段错误",我知道它来自我的" mb_init"函数,因为我不太清楚如何处理嵌套结构。 如何使用嵌套结构设置来自此init函数的消息大小?

感谢任何帮助..我正在学习C;对不起,如果有些事情不是最有效的"要做的事。

2 个答案:

答案 0 :(得分:2)

编译器警告(-Wall)指出了问题。

test.c:27:12: warning: variable 'myMailbox' is uninitialized when used here [-Wuninitialized]
   mb_init(myMailbox, MAILBOX_SIZE);
           ^~~~~~~~~
1 warning generated.

您在myMailbox中传递并使用它而没有为其分配内存。通常,不要传入指向初始化函数的指针,返回一个。

您也不应该在邮箱中初始化空邮件,只需初始化邮箱即可。让任何人添加消息都会初始化消息并将其传入。

Mailbox *mb_init(int size){
        Mailbox *sb = malloc(sizeof(Mailbox));

        sb->queue = NULL;
        sb->in = 0;
        sb->out = 0;
        sb->cnt = 0;

        return sb;
}

这将我们带到下一个问题:您只在队列中为一条消息分配了空间。并且它不存储指向消息的指针,它必须复制它们并且它们会变得很大。

相反,请使用Message指针数组。

const size_t MAILBOX_SIZE = 10;

typedef struct {
        size_t bytes;
        void *data;
} Message;

typedef struct {
        Message **queue;
        size_t in; //place to add next element in buffer
        size_t out; //place to remove next element in buffer
        size_t cnt; //number of elements in buffer
        size_t max_size;
} Mailbox;

Mailbox *mb_init(size_t size){
        Mailbox *mb = malloc(sizeof(Mailbox));
        mb->queue = malloc(sizeof(Message*) * size);
        mb->in = 0;
        mb->out = 0;
        mb->cnt = 0;
        mb->max_size = size;

        return mb;
}

void mb_destroy( Mailbox *mb ) {
    free(mb->queue);
    free(mb);
}

我做了一些其他改动。最明显的是切换到size_t来存储事物的大小。这可以避免碰到整数限制。

我添加了一个析构函数,你应该总是为你的所有结构编写一个初始化器和析构函数。

邮箱现在存储其最大尺寸。它需要知道这一点,以避免添加太多消息。此版本的更高版本将切换到链接列表或根据需要重新分配队列。

我还确保始终使用typedef,而不是基础结构类型,并且甚至从结构中删除名称,因此无法直接引用它们。现在只有一种方法可以引用结构,这样更容易阅读。如果对类型进行彻底更改,它还提供更强的封装,例如切换到索引其他存储的整数(不太可能,但你永远不知道)。

答案 1 :(得分:1)

正如我已经说过的,你的问题是通过价值而不是通过参考传递。

有很多方法可以做到这一点。你可以尝试这个

  

在Main

Mailbox myMailbox;                 // memory allocated on the stack, life span till the *return*
mb_init(&myMailbox, MAILBOX_SIZE); // pass the address here
// and don't forget to free the queue memory when you are done with it



//Main ends here




/* In your code if you don't return a pointer to the memory allocated here on the heap. 
You will not get those changes when the function return from the stack. 
It is best practice to return a pointer to the allocated heap memory
 before the function returns. */

void mb_init(Mailbox *sb, int size){
        ......
        ......

}