初始化嵌套的void指针

时间:2014-10-22 15:19:26

标签: c pointers struct malloc

我有一个结构,它将一些数据存储为void指针和这样的整数:

 struct container
 {
   int size;
   void* data;
 };

现在我有了第二个结构:

 struct date
 {
   int day;
   int year;
 };

我有初始化这样一个容器并返回它的函数:

struct container get_container()
{
    struct container d = { .data=  {(struct date){.day = 1, .year = 2}, (struct date){.day = 4, .year = 5}}, .size = 2};
    return d;
}

但是当我编译代码时,编译器会抱怨类型不匹配:

test.c:19:34: error: initializing 'void *' with an expression of incompatible type 'struct date'
        struct container d = { .data=  {(struct date){.day = 1, .year = 2}, (struct date){.day = 4, .year = 5}}, .size = 2};
                                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.

即使我将一个void *强制转换为init,它也不起作用。有没有办法做到这一点,不使用malloc?

2 个答案:

答案 0 :(得分:4)

要使初始化程序能够编译,您需要使用复合文字(它也与您正在使用的指定初始化程序一起添加到C99中):

struct container d =
{
    .data = (struct date[]){ { .day = 1, .year = 2 }, { .day = 4, .year = 5 } },
    .size = 2
};

确定返回该结构的副本是否“安全”更难。问题是在函数返回之后是否继续存在日期数组(它没有)以及是否可以通过返回指针的代码安全地修改它(它可以)。

感谢2501指出要在comment中查看的位置。

  

ISO / IEC 9899:2011

     

§6.2.4对象的存储持续时间,¶6 [讨论自动持续时间对象] ...如果为对象指定了初始化,则每次执行初始化时都会执行在块的执行中达到声明或复合文字;否则,每次达到声明时,该值将变为不确定。

     

§6.5.2.5复合文字,¶5复合文字的值是初始化列表初始化的未命名对象的值。如果复合文字出现在函数体外,则该对象具有静态存储持续时间;否则,它有自动存储持续时间   封闭的块。

因此,要将指针返回到日期数组,您需要使用显式内存分配(malloc()等)。据推测,您将拥有其他容器,其中包含的数据类型不仅仅是struct date - 否则,您将滥用void *(使用struct date *代替,或考虑灵活数组成员的优点)

答案 1 :(得分:2)

您尝试将结构值分配给无效指针的void指针。您需要获取结构的地址并将data指定给它。这意味着您需要使用malloc。如果您没有使用malloc,那么您将获取一个指向本地堆栈变量的指针,该变量将消失""一旦它在结束时声明它的功能,它的帧从堆栈中弹出。那时你的指针就不会指向你所期望的。