关于编译器警告,我真的很痴迷。它们可以帮助我调试很多问题,因此我尝试摆脱所有问题。
我有2个子结构,我们称它们为ChildA
和ChildB
和一个基本结构Base
。
// predefines.h
typedef struct sBase Base;
typedef struct sChildA ChildA;
typedef struct sChildB ChildB;
// base.h
typedef struct sBase {
// Base fields
} Base;
// child_a.h
typedef struct sChildA {
Base* base;
// other things
} ChildA;
// child_b.h
typedef struct sChildB {
Base* base;
// other things
} ChildB;
应该没事吧?它行之有效,除了它在我的代码周围生成了如此多的警告之外,其他警告,我只是在我的IDE中没有注意到它们,因为我看到的很多黄色。
我有很多功能,例如:
void do_something(Base* base) {
// Code code code
}
do_something(instance_of_child_a); // Warning here
有没有什么方法可以使编译器满意而不禁用这种类型的警告?谢谢你。
编辑:这是警告:
注意:预期为“ Base * {aka struct sBase *}”,但参数类型为 ‘ChildA * {aka结构sChildA }” void do_something(LitBase base);
答案 0 :(得分:2)
您收到警告,因为ChildA*
与Base*
不兼容。它们显然是不同的结构类型。并且由于它们不兼容(在此上下文中,含义相同),因此编译器无法在它们之间进行隐式转换。这不是一些令人讨厌的“误报”,而是一种不应忽略的C语言违规。许多编译器会给出错误并拒绝生成二进制文件。
您必须使用显式强制转换或简单地手动传递.base
成员。
显式强制转换的另一个替代方法是包装宏:
void base_do_something (Base* base);
#define do_something(x) \
base_do_something ( \
_Generic( (x), ChildA*: &(x)->base, ChildB*: &(x)->base ) \
)
或等效名称:
#define do_something(x) \
base_do_something ( \
_Generic( (x), ChildA*: (Base*)(x), ChildB*: (Base*)(x) ) \
)
正如后面的示例所示,它实际上很有效,根据C17 6.7.2.1§15是有效的。并且它没有违反严格的别名,因为ChildA
等是其成员之间包含Base
的聚合。如果您不是语言律师,请使用第一个示例:)