让我说我有这样的结构:
typedef struct myInfo {
WORD myCount;
WORD data[0];
} myInfo;
好吧,我想在另一个.c源文件中使用这个结构(顺便声明为extern),其中我有一个这样的函数:
void dynamic_init(struct myInfo dummy){
macroPut(5, dummy.myCount, &dummy.mydata); <- doesn't work
macroPut(5, dummy.myCount, &externalInitialized.mydata); <- works
}
这样我就可以动态使用这个dynamic_init而不用担心结构名称... 但是你可以很容易地在上面的代码片段中看到它,它只适用于inizialized结构...但是如果我用这种方式调用函数:
dynamic_init(externalInitialized);
它不会工作。
换句话说,我必须做这样的事情:
dynamic_init( externalInitialized.myCount, externalInitialized.mydata);
我有预期的结果。
主要的谜团是&#34; mydata&#34;那腐败一切的词。 &#34; myCount&#34;如果我这样做,按预期工作:
dynamic_init( externalInitialized, externalInitialized.mydata);
然后:
void dynamic_init(struct externalInitialized dummy,WORD * dynData){
macroPut( 5, dummy.myCount, &dynData); <- works
}
我知道这是愚蠢的,但只是为了表明错误的部分。
谢谢!
答案 0 :(得分:1)
当您将结构传递给函数时,编译器会生成复制结构内容的代码,因此函数会获得自己的参数副本,它可以自由修改而不会影响原始参数。正在为sizeof struct
个字节执行复制。
这里的主要问题是你的结构有flexible array member,所以它的sizeof
与它将占用的实际尺寸关系不大。
E.g。问题sizeof
中的结构是4(最后一个字段是0个元素的数组,所以它不会增加sizeof),但是当你为结构分配内存时,你实际上分配了更多 - 并且在结构字段中保存了'实际'大小。这样,访问data
数组实际上会获得结构本身之外的元素(放在它的下一个字节);但是,编译器不知道(并且无法知道,因为大小因一个结构实例而异)。出于同样的原因,你不能直接将该结构放在堆栈上并安全地填充数据 - 因为这将触及不属于它的字节并破坏其他东西(从技术上讲它可以放在堆栈上,但你必须在其中手动对齐它堆栈数组足够大。)
灵活的数组成员有其他限制,比如你不能制作那种类型的结构数组(再一次 - 技术上你可以,但没有意义,因为数组索引依赖于sizeof
)。
因此,简短的回答是“不要按价值传递灵活大小的结构”。或者甚至在按值传递结构之前三思而后行 - 毕竟复制并不是免费的。