避免警告:应为“const struct aiocb * const*”,但参数类型为“struct aiocb **”

Avoid warning: expected ‘const struct aiocb * const*’ but argument is of type ‘struct aiocb **’

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++ 可能会提供一个解决方案,但我认为该解决方案对我来说不是很有用。谢谢。

这里有一种调用函数的方法 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 ... */