摆脱由 typedef 引起的 "Incompatible pointer" 警告
Get rid of "Incompatible pointer" warning caused by typedef
关于编译器警告,我真的很迂腐。他们帮助我调试了很多问题,所以我尝试摆脱所有问题。
我有 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
有什么方法可以让编译器满意而无需禁用此类警告?非常感谢。
编辑: 这里是警告:
note: expected ‘Base * {aka struct sBase *}’ but argument is of type
‘ChildA * {aka struct sChildA }’ void do_something(LitBase base);
您收到警告是因为 ChildA*
与 Base*
不兼容。它们显然是不同的结构类型。并且由于它们不兼容(在此上下文中意味着相同),编译器无法在它们之间进行隐式转换。这不是一些烦人的"false positive",而是一个不容忽视的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
。如果您不是语言律师,请使用第一个示例:)
关于编译器警告,我真的很迂腐。他们帮助我调试了很多问题,所以我尝试摆脱所有问题。
我有 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
有什么方法可以让编译器满意而无需禁用此类警告?非常感谢。
编辑: 这里是警告:
note: expected ‘Base * {aka struct sBase *}’ but argument is of type ‘ChildA * {aka struct sChildA }’ void do_something(LitBase base);
您收到警告是因为 ChildA*
与 Base*
不兼容。它们显然是不同的结构类型。并且由于它们不兼容(在此上下文中意味着相同),编译器无法在它们之间进行隐式转换。这不是一些烦人的"false positive",而是一个不容忽视的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
。如果您不是语言律师,请使用第一个示例:)