【问题标题】:Avoid warning: expected ‘const struct aiocb * const*’ but argument is of type ‘struct aiocb **’避免警告:预期为“const struct aiocb * const*”,但参数的类型为“struct aiocb **”
【发布时间】:2019-05-30 20:11:24
【问题描述】:
archives.c: In function ‘fd_writeback_wait’:
archives.c:121:21: warning: passing argument 1 of ‘aio_suspend’ from incompatible pointer type [-Wincompatible-pointer-types]
     r = aio_suspend(&cb, 1, NULL);
                     ^~~
In file included from ../lib/dpkg/fsys.h:28,
                 from ../lib/dpkg/triglib.h:28,
                 from archives.c:57:
/usr/include/aio.h:168:51: note: expected ‘const struct aiocb * const*’ but argument is of type ‘struct aiocb **’
 extern int aio_suspend (const struct aiocb *const __list[], int __nent,
                         ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~

解释:

我认为没有办法避免这个警告,除非编写一个危险的类型转换来更改 const 限定符,或者禁止整个警告类别。

显然 C++ 在这里做得更好。它还有const_cast 用于更清晰的转换,确保您更改 const 限定符。

换句话说,POSIX 将aio_suspend() 定义为像这样使用const 可以说是相当危险的。

我的解释正确吗?

如果我错了,那么我该如何避免这个警告,但仍然让编译器检查我只是在转换 const 限定符,而不是转换为完全不兼容的类型?


我怀疑如果有方法,它们不会是我想在实践中使用的方法,但我很好奇。

我正在处理的当前代码没有明确记录所需的编译器版本。

我会对在标准 C 版本中工作的技术感兴趣。我很想听听 GCC 扩展。也欢迎评论是否推荐或不推荐定义这样的函数参数。

提醒读者注意,C 和 C++ 是不同的,不是 100% 兼容的语言。我承认将代码库切换到 C++ 可能会提供一个解决方案,但我认为该解决方案对我来说不是很有用。谢谢。

【问题讨论】:

    标签: c linux constants posix


    【解决方案1】:

    这是一种使用适当的constness 调用函数的方法:

    struct aiocb cb;
    const struct aiocb * cblist[1] = { &cb };
    aio_suspend(cblist, 1, NULL);
    

    或者:

    struct aiocb cb;
    const struct aiocb * cbptr = &cb;
    aio_suspend(&cbptr, 1, NULL);
    

    请注意,提出上述答案是因为您使用了以下语法:

    r = aio_suspend(&cb, 1, NULL);
    

    cb 的地址传递给需要指向指针的东西意味着cb 是一个指针,所以这个调用只对单个元素数组有意义。

    假设你的警告是因为你确实有这个:

    struct aiocb *cbv[256];
    r = aio_suspend(cbv, 256, NULL);
    

    删除警告很容易。使用(void *)

    r = aio_suspend((void *)cbv, 256, NULL);
    

    但是,首先将向量定义为使用指向const 的指针会更好。

    const struct aiocb *cbv[256];
    r = aio_suspend(cbv, 256, NULL);
    

    如果每个回调实例在现实中确实是可修改的(例如,由malloc 分配),那么在修改之前丢弃 const。

    struct aiocb *cb = (struct aiocb *)cbv[i];
    /* ... modify cb ... */
    

    【讨论】:

    • 点!对于呼叫站点,这个确切的警告是关于的,那很好。但我也有一个调用站点,其中数组最多有 256 个条目,并且被修改和重用。即使可以将整个数组复制到一个 const 局部变量中,并且即使优化器知道如何省略复制,我怀疑这不是非常惯用的 C 代码。
    • @sourcejedi:您实际上并没有提出这样的用例。尽管如此,我还是扩大了答案。
    • 完全同意,我很抱歉:-)。 Nitpick:如果 cb 被声明为 struct aiocb *cb[1]cb&cb 都可以工作 - 数组就像那样很奇怪。如果您猜到我没有这样编写代码,那您是对的 :-)。
    • 他们可能有相同的地址,但他们有不同的类型。 tio.run/…
    • FWIW,在正确的位置添加一些 const 限定符现在既避免了编译器警告,也避免了任何类型转换以添加/删除 const 的需要。看来 POSIX aio_suspend() 毕竟是完全可用的:-)。谢谢。
    猜你喜欢
    • 2012-04-08
    • 1970-01-01
    • 2023-04-08
    • 2020-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多