来自结构的函数中的指针不起作用
Pointer in Function from a Struct not working
假设我有一个这样的结构:
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 而不必担心结构名称...
但是正如您在上面的代码片段中很容易看到的那样,它仅适用于初始化结构......但是如果我这样调用函数:
dynamic_init(externalInitialized);
不行。
换句话说,我必须做这样的事情:
dynamic_init( externalInitialized.myCount, externalInitialized.mydata);
我得到了预期的结果。
主要的谜团是 "mydata" WORD 破坏了一切。
如果我这样做,"myCount" 会按预期工作:
dynamic_init( externalInitialized, externalInitialized.mydata);
然后:
void dynamic_init(struct externalInitialized dummy, WORD *dynData){
macroPut( 5, dummy.myCount, &dynData); <- works
}
我知道这很蠢,但它只是为了显示确切的错误部分。
谢谢!
当您将结构传递给函数时,编译器会生成代码来复制结构内容,因此函数会获得自己的参数副本,可以在不影响原始参数的情况下自由修改。复制执行 sizeof struct
个字节。
你这里的主要问题是你的结构有 flexible array member,所以它的 sizeof
与它实际占用的大小关系不大。
例如有问题的结构 sizeof
是 4(最后一个字段是 0 元素的数组,所以它不会增加 sizeof),但是当你为结构分配内存时,你实际上分配了更多 - 并节省了 'real' 大小结构域。这样,访问 data
数组实际上将获取结构本身之外的元素(放置在它的下一个字节的右边);然而,编译器并不知道(也无法知道,因为一个结构实例的大小与另一个结构实例不同)。出于同样的原因,您不能直接将该结构放在堆栈上并安全地填充数据 - 因为这会触及不属于它的字节并破坏其他东西(从技术上讲,它可以放在堆栈上,但您必须在其中手动对齐它足够大小的堆栈数组)。
灵活的数组成员有其他限制,比如你不能创建这种类型结构的数组(再一次 - 技术上你可以,但它没有意义,因为数组索引依赖于 sizeof
)。
所以,简短的回答是 "don't pass flexible-sized structures by value"。或者甚至在按值传递结构之前三思而后行 - 毕竟复制不是免费的。
假设我有一个这样的结构:
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 而不必担心结构名称... 但是正如您在上面的代码片段中很容易看到的那样,它仅适用于初始化结构......但是如果我这样调用函数:
dynamic_init(externalInitialized);
不行。
换句话说,我必须做这样的事情:
dynamic_init( externalInitialized.myCount, externalInitialized.mydata);
我得到了预期的结果。
主要的谜团是 "mydata" WORD 破坏了一切。 如果我这样做,"myCount" 会按预期工作:
dynamic_init( externalInitialized, externalInitialized.mydata);
然后:
void dynamic_init(struct externalInitialized dummy, WORD *dynData){
macroPut( 5, dummy.myCount, &dynData); <- works
}
我知道这很蠢,但它只是为了显示确切的错误部分。
谢谢!
当您将结构传递给函数时,编译器会生成代码来复制结构内容,因此函数会获得自己的参数副本,可以在不影响原始参数的情况下自由修改。复制执行 sizeof struct
个字节。
你这里的主要问题是你的结构有 flexible array member,所以它的 sizeof
与它实际占用的大小关系不大。
例如有问题的结构 sizeof
是 4(最后一个字段是 0 元素的数组,所以它不会增加 sizeof),但是当你为结构分配内存时,你实际上分配了更多 - 并节省了 'real' 大小结构域。这样,访问 data
数组实际上将获取结构本身之外的元素(放置在它的下一个字节的右边);然而,编译器并不知道(也无法知道,因为一个结构实例的大小与另一个结构实例不同)。出于同样的原因,您不能直接将该结构放在堆栈上并安全地填充数据 - 因为这会触及不属于它的字节并破坏其他东西(从技术上讲,它可以放在堆栈上,但您必须在其中手动对齐它足够大小的堆栈数组)。
灵活的数组成员有其他限制,比如你不能创建这种类型结构的数组(再一次 - 技术上你可以,但它没有意义,因为数组索引依赖于 sizeof
)。
所以,简短的回答是 "don't pass flexible-sized structures by value"。或者甚至在按值传递结构之前三思而后行 - 毕竟复制不是免费的。