【问题标题】:Ignore "initialization from incompatible pointer type" warnings?忽略“从不兼容的指针类型初始化”警告?
【发布时间】:2009-11-19 14:19:59
【问题描述】:

是否有编译器指令可以忽略Hardware_MouseDrivers_GPM_MethodsHardware_MouseDrivers_DevInput_Methods 中的“从不兼容的指针类型初始化”警告?但是,全局关闭警告不是一种选择。

#include <stdio.h>

/* Mouse driver interface */

typedef struct _Hardware_MouseDriver {
        int (*open)(void*, char *);
        int (*close)(void*);
        int (*poll)(void*);
} Hardware_MouseDriver;

/* GPM */

typedef struct _Hardware_MouseDrivers_GPM {
        char *path;
} Hardware_MouseDrivers_GPM;

static int Hardware_MouseDrivers_GPM_Open(Hardware_MouseDrivers_GPM *this, char *path);
static int Hardware_MouseDrivers_GPM_Close(Hardware_MouseDrivers_GPM *this);
static int Hardware_MouseDrivers_GPM_Poll(Hardware_MouseDrivers_GPM *this);

static int Hardware_MouseDrivers_GPM_Open(Hardware_MouseDrivers_GPM *this, char *path) {
        printf("GPM: Opening %s...\n", path);
        this->path = path;
}

static int Hardware_MouseDrivers_GPM_Close(Hardware_MouseDrivers_GPM *this) {
        printf("GPM: Closing %s...\n", this->path);
}

static int Hardware_MouseDrivers_GPM_Poll(Hardware_MouseDrivers_GPM *this) {
        printf("GPM: Polling %s...\n", this->path);
}

Hardware_MouseDriver Hardware_MouseDrivers_GPM_Methods = {
        .open  = Hardware_MouseDrivers_GPM_Open,
        .close = Hardware_MouseDrivers_GPM_Close,
        .poll  = Hardware_MouseDrivers_GPM_Poll
};

/* DevInput */

typedef struct _Hardware_MouseDrivers_DevInput {
        char *path;
} Hardware_MouseDrivers_DevInput;

static int Hardware_MouseDrivers_DevInput_Open(Hardware_MouseDrivers_DevInput *this, char *path);
static int Hardware_MouseDrivers_DevInput_Close(Hardware_MouseDrivers_DevInput *this);
static int Hardware_MouseDrivers_DevInput_Poll(Hardware_MouseDrivers_DevInput *this);

static int Hardware_MouseDrivers_DevInput_Open(Hardware_MouseDrivers_DevInput *this, char *path) {
        printf("DevInput: Opening %s...\n", path);
        this->path = path;
}

static int Hardware_MouseDrivers_DevInput_Close(Hardware_MouseDrivers_DevInput *this) {
        printf("DevInput: Closing %s...\n", this->path);
}

static int Hardware_MouseDrivers_DevInput_Poll(Hardware_MouseDrivers_DevInput *this) {
        printf("DevInput: Polling %s...\n", this->path);
}

Hardware_MouseDriver Hardware_MouseDrivers_DevInput_Methods = {
        .open  = Hardware_MouseDrivers_DevInput_Open,
        .close = Hardware_MouseDrivers_DevInput_Close,
        .poll  = Hardware_MouseDrivers_DevInput_Poll
};

/* Test drivers */

void TestDriver(Hardware_MouseDriver driver, void *data) {
        /* Access the driver using a generic interface
         * (Hardware_MouseDriver) */
        driver.poll(data);
}

void main() {
        Hardware_MouseDrivers_GPM gpm;
        Hardware_MouseDrivers_DevInput devinput;

        Hardware_MouseDrivers_GPM_Open(&gpm, "/dev/gpmctl");
        Hardware_MouseDrivers_DevInput_Open(&devinput, "/dev/input/mice");

        TestDriver(Hardware_MouseDrivers_GPM_Methods, &gpm);
        TestDriver(Hardware_MouseDrivers_DevInput_Methods, &devinput);

        Hardware_MouseDrivers_GPM_Close(&gpm);
        Hardware_MouseDrivers_DevInput_Close(&devinput);
}

【问题讨论】:

  • 需要更多信息。您的代码的哪一部分具体是警告?您可以发布 GCC 输出吗?您可以使用一个不会给您警告的标志 - 但这是您通常不想忽略的警告。
  • 正如我所说,这些警告出现在“Hardware_MouseDrivers_GPM_Methods”和“Hardware_MouseDrivers_DevInput_Methods”的定义中(ll. 35-38, 64-67)。 GCC 告诉我“警告:从不兼容的指针类型初始化”。是的,确实有一个标志,但它会在全球范围内关闭这些警告,这是危险的。为什么忽略这些警告是错误的?
  • 嗯,因为这是纯 C,所以下面可能会起作用(我现在没有 ggc 环境,如果它不起作用,请耐心等待):.open = (void*)Hardware_MouseDrivers_DevInput_Open,
  • 太棒了!这完美无缺。谢谢尼古拉斯。 :)
  • 啊,C 的美……(当移植到 C++ 时,这会在后面咬你)。更新/编辑了我的答案。

标签: c gcc


【解决方案1】:

将赋值转换为正确的类型(带有 void * 的函数指针,而不是您的实例指针):

 .open= (int (*)(void*, char *))Hardware_MouseDrivers_GPM_Open;

或者做一个类型,在struct的定义和初始化中使用:

typedef int (*openfcnt_t)(void*, char *);

typedef struct _Hardware_MouseDriver {
        openfnct_t open;
} Hardware_MouseDriver;

然后

 .open= (openfnct_t)Hardware_MouseDrivers_GPM_Open;

编辑:

经过进一步思考,对于 C 程序来说,最简单和最不繁琐的方法是:

 .open= (void *)Hardware_MouseDrivers_GPM_Open;

【讨论】:

  • 这也是我的想法。但是,为每个函数引入 typedef 会使代码变得更大,但并没有提供任何真正的好处。与 (int ()(void, char *)) 相比,openfcnt_t 转换更短且更不容易出错,但两种解决方案仍然需要添加大量不必要的额外代码。它们并不是我想要的。是否有任何编译器指令(如#ifdef、#define 等)来关闭所有与指针类型相关的警告,而不是全局但暂时针对某个代码块?
  • 也许这个会有所帮助:stackoverflow.com/questions/965093/…
  • 我认为这不是一个好主意。您实际调用的函数与调用中使用的原型不匹配,这可能是一件危险的事情。这里的演员比关闭警告更好地隐藏了可能的问题,并且可能的问题不是您想要隐藏的东西。
  • @Thomas:类型转换始终意味着“类型似乎不匹配,但我知道我在做什么”,因此您的评论基本上适用于所有类型的转换。警告就是……一个警告……而演员表是你告诉编译器无论如何都可以的方式。
  • @Nicholaz:同意类型转换的含义。但是,另一方面,您需要真正确定自己确实确​​实知道自己在做什么,并且如果有人将其移植到具有不同大小指针(近!远!)的某些架构,那么也许你已经不知道了……那么,为什么不按正确的方式去做,也许不是上帝,但至少是 ANSI 委员会想要的方式!
【解决方案2】:

我想这个问题的明显答案是“为什么不修复代码以使用正确的指针类型”?

编辑

好的,我可以理解您不想使代码不必要地复杂化,但我认为这不是那么复杂,甚至是不必要的。

让我们看看 Hardware_MouseDriver 结构中的 open 字段,它应该是一个指向函数的指针,该函数将指向 void 的指针作为其第一个参数。

要初始化此字段,请使用指向函数 Hardware_MouseDrivers_GPM_Open 的指针,并在另一个地方使用指向函数 Hardware_MouseDrivers_DevInput_Open 的指针。这些都没有将指向 void 的指针作为第一个参数,这当然是编译器警告的内容。

现在,if void 指针与这些指针的大小相同,并且它们的存储和处理方式之间没有其他令人惊讶的差异,通过 open 指针将按预期工作。很可能会,而且我猜想使用这种类型的低级代码,不太可能有人将它移植到 TOPS-20 或其他东西上。但不能保证它 会起作用的,它看起来(对我来说)很奇怪。 (对于编译器,显然!)

所以我的建议是像这样更改代码:

static int Hardware_MouseDrivers_GPM_Open(Hardware_MouseDrivers_GPM *this, char *path) {
    printf("GPM: Opening %s...\n", path);
    this->path = path;
}

稍微复杂一点:

static int Hardware_MouseDrivers_GPM_Open(void *arg1, char *path) {
    Hardware_MouseDrivers_GPM *this = arg1;
    printf("GPM: Opening %s...\n", path);
    this->path = path;
}

我认为这种更改会比 (1) 关闭警告、(2) 记录它以便读者可以理解为什么该警告在这里不重要、(3) 记录更多内容更容易,也更简单所以你的读者实际上相信你知道你在做什么,并且 (4) 处理如果有人真的确实将你的代码移植到 TOPS-20 会出现的问题。

【讨论】:

  • 嗯,不是所有指针的大小都一样吗?我确实理解您喜欢您的方法的原因,但通过额外的演员阵容没有附加价值。我想,汇编代码甚至不会有所不同。这只是编译器打印的一条消息,目的是警告您可能在您的代码中存在意外错误。问题是添加的代码,其唯一目的是满足编译器,是否真的值得付出努力。我不这么认为。
  • @Timn:嗯,就像警告一样。你要么得到它们,要么把它们关掉。如果你让它们打开,你将不得不添加某种代码(C代码或编译器编译指示)来告诉编译器在这个地方你知道你在做什么。要么通过赋值将类型放入适当的位置(就像在我的解决方案中一样),要么为编译器提供正确的函数类型(Thomas 的解决方案),然后稍后将指针类型转换成您想要的形式。一种或另一种方式会有额外的代码。
  • @Timn:是的,在今天的大多数(所有?)系统上,所有指针的大小都相同,在这样的系统上,汇编程序可能是相同的。但是标准并不能保证这一点,所以明年左右英特尔的某个人可能会决定将地址空间分成具有不同大小指针的段会提高效率,然后 void 指针可能是 64 位,而您的 struct 指针可能为 32 位。你的代码会坏掉。然后您将很难找到问题,因为您要么使用显式强制转换隐藏它,要么关闭警告...... :)
【解决方案3】:

我遇到了这个问题,经过仔细检查,我决定我不应该收到这个消息。结构中的类似行不会产生此错误。

使用(void *) function_name 修复它。

这让我不必检查 gcc 树。

【讨论】:

    猜你喜欢
    • 2013-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-21
    • 1970-01-01
    • 2021-06-27
    • 2011-09-01
    相关资源
    最近更新 更多