当谈到编译器警告时,我真的很迂腐。它们帮助我调试了很多问题,所以我试着把它们都去掉。
我有两个子结构,我们称它们为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 structsBase*}",但参数的类型为"ChildA*{aka structsChildA}"void do_something(LitBasebase(;
由于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
的聚合,因此它不违反严格的混叠。如果你不是一名语言律师,请使用第一个例子:(