我有一个结构,它将一些数据存储为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?
答案 0 :(得分:4)
要使初始化程序能够编译,您需要使用复合文字(它也与您正在使用的指定初始化程序一起添加到C99中):
struct container d =
{
.data = (struct date[]){ { .day = 1, .year = 2 }, { .day = 4, .year = 5 } },
.size = 2
};
确定返回该结构的副本是否“安全”更难。问题是在函数返回之后是否继续存在日期数组(它没有)以及是否可以通过返回指针的代码安全地修改它(它可以)。
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,那么您将获取一个指向本地堆栈变量的指针,该变量将消失""一旦它在结束时声明它的功能,它的帧从堆栈中弹出。那时你的指针就不会指向你所期望的。