首页 > 解决方案 > 在函数结构上静默 WCast-function-type

问题描述

我有以下警告:

cast between incompatible function types from ‘int (*)(pile *)’ {aka ‘int (*)(struct pile *)’} to ‘void (*)(void *)’ [-Wcast-function-type] 

我不知道如何解决此警告。

结构

typedef struct conteneur_sommets {
  void *donnees;
  int (*est_vide)(void *);
  void (*ajouter)(void *, int);
  void (*supprimer)(void *);
  int (*choisir)(void *);
  void (*detruire)(void *);
} conteneur_sommets;

关联功能

conteneur_sommets *cs_creer_pile(int n)
{
  conteneur_sommets cs = {.donnees   = pile_creer(n),
              .est_vide  = (int (*)(void *))        pile_est_vide,
              .ajouter   = (void (*)(void *, int))  pile_empiler,
              .supprimer = (void (*)(void *))       pile_depiler, <- warning cast
              .choisir   = (int (*)(void *))        pile_sommet,
              .detruire  = (void (*)(void *))       pile_detruire};
  return cs_creer(&cs);
}

void cs_supprimer(conteneur_sommets *cs)
{
  cs->supprimer(cs->donnees);
}

标签: ccastingwarningscompiler-warnings

解决方案


虽然完全抑制警告有时会很有用,但通常最好在代码级别解决问题。这里的问题是您的声明是错误的,这是首先触发警告的原因。首先避免将结构/联合的定义和typedef别名的声明结合起来。最好将它们分开,这样您可以在必要时分开声明和定义。

typedef struct conteneur_sommets conteneur_sommets;

conteneur_sommets这将创建不透明结构的别名struct conteneur_sommets。这也称为前向声明。前向声明一般放在头文件中。

现在我们可以定义结构

struct conteneur_sommets {
    void *donnees;
    int (*est_vide)(conteneur_sommets *);
    void (*ajouter)(conteneur_sommets *, int);
    void (*supprimer)(conteneur_sommets *);
    int (*choisir)(conteneur_sommets *);
    void (*detruire)(conteneur_sommets *);
};

这样,您就不需要转换函数指针并保存类型检查是否具有正确的签名。

conteneur_sommets cs = {.donnees   = pile_creer(n),
          .supprimer = pile_depiler};

其次,C 程序员很少意识到的一件事是,可以定义函数原型的 typedef 别名,而不是函数指针,而是直接定义原型。即使非常不寻常,有时这确实可以使代码更具可读性。让我用你的代码举一个例子:

typedef int  est_vide_fn (conteneur_sommets *);
typedef void ajouter_fn  (conteneur_sommets *, int);
typedef void supprimer_fn(conteneur_sommets *);
typedef int  choisir_fn  (conteneur_sommets *);
typedef void detruire_fn (conteneur_sommets *);

this 声明了五个函数原型类型定义。

该结构现在可以声明为

struct conteneur_sommets {
    void *donnees;
    est_vide_fn  *est_vide;
    ajouter_fn   *ajouter;
    supprimer_fn *supprimer;
    choisir_fn   *choisir;
    detruire_fn  *detruire;
};

您的cs_supprimer函数原型可以通过以下方式声明

supprimer_fn cs_supprimer;

其实现定义如前

void cs_supprimer(conteneur_sommets *cs)
{
    cs->supprimer(cs->donnees);
}

推荐阅读