摆脱由typedef引起的“不兼容指针”警告

时间:2018-12-14 09:53:54

标签: c gcc compilation compiler-warnings

关于编译器警告,我真的很痴迷。它们可以帮助我调试很多问题,因此我尝试摆脱所有问题。

我有2个子结构,我们称它们为ChildAChildB和一个基本结构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);

1 个答案:

答案 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的聚合。如果您不是语言律师,请使用第一个示例:)