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

时间:2019-05-30 20:11:25

标签: c linux const posix

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

1 个答案:

答案 0 :(得分:2)

这是一种以适当的const身份调用函数的方法:

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 ... */