首页 > 解决方案 > 摆脱由 typedef 引起的“不兼容指针”警告

问题描述

当谈到编译器警告时,我真的很迂腐。它们帮助我调试了很多问题,所以我尝试摆脱所有这些问题。

我有 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 struct sChildA }' void do_something(LitBase base);

标签: cgcccompilationcompiler-warnings

解决方案


您收到警告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 有效的。而且它不违反严格的别名,因为ChildAetc 是包含Base在其成员之间的聚合。如果您不是语言律师,请使用第一个示例 :)


推荐阅读