Избегайте предупреждений: ожидается ‘const struct aiocb * const*’, но аргумент имеет тип ‘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++, вероятно, мог бы стать решением, но я не думаю, что это решение было бы очень полезным для меня. Спасибо.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
861
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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 записей, и он модифицируется и используется повторно. Даже если можно скопировать весь массив в константную локальную переменную и даже если оптимизатор знает, как исключить копию, я подозреваю, что это не будет очень идиоматичным кодом C.

sourcejedi 30.05.2019 22:35

@sourcejedi: на самом деле вы не представили такой вариант использования. Тем не менее я расширил свой ответ.

jxh 30.05.2019 22:47

Абсолютно согласен, и я извиняюсь :-). Придирка: и cb, и &cb работают, если cb объявлен как struct aiocb *cb[1] — массивы такие странные. Вы были бы правы, если бы догадались, что я не писал свой код так :-).

sourcejedi 30.05.2019 22:55

У них может быть один и тот же адрес, но разные типы. tio.run/…

jxh 30.05.2019 22:58

FWIW, добавление нескольких квалификаторов const в нужном месте теперь позволяет избежать как предупреждения компилятора, так и необходимости любых приведений типов для добавления/удаления констант. Кажется, что POSIX aio_suspend() в конце концов вполне пригоден для использования :-). Спасибо.

sourcejedi 30.05.2019 23:03

Другие вопросы по теме