У меня есть встроенное программное обеспечение C, которое требует нескольких константных указателей для константных данных. До сих пор я повторял две строки кода для их инициализации:
const int data = 0xF0; // const int
const int* const buffer = &data; // const pointer to const int
Раньше я использовал множество приведений типов, но при проверке товарищами по команде обнаружил, что это слишком подвержено ошибкам. Я открыт для их использования, если смогу найти способ использовать их четко и последовательно.
Мне также нужно избегать отбрасывания квалификатора const
при переходе к функциям, поскольку его отбрасывание фактически уже привело к одной ошибке в разработке.
Возможно, #define DEFCONSTS(var, ptr, val, t) const t var = val; const t *const ptr = &var
, который в вашем примере будет использоваться как DEFCONSTS(data, buffer, 0xF0, int);
.
Использование константных переменных-указателей не имеет смысла, почему вам нужен объект-указатель, который не может измениться. Вместо этого используйте объект, на который ссылаются. Они имеют смысл только как параметры функции.
«Раньше я использовал множество приведений типов, но обнаружил, что это слишком подвержено ошибкам». Вы можете показать, как вы использовали приведения типов. Это только для того, чтобы «удалить» квалификатор const
?
«поскольку отказ от этого уже вызвал одну ошибку в разработке». Тогда использование указателей на значения const
изначально некорректно. Но без более подробной информации о вашем использовании трудно предложить альтернативу.
@0___________ ты поднял ценную задачу по кадрам, спасибо. Требуется больше кофе.
Пожалуйста, опубликуйте код функции, которую необходимо const
удалить.
Используйте составной литерал:
const int * const buffer = (const int []) { 0xF0 };
или:
const int * const buffer = & (const int) { 0xF0 };
Вы можете определить указатель и данные в одном объявлении (хотя это нечитабельно и не рекомендуется:
const int data = 0xF0, * const buffer = &data;
Используя составные литералы C99, вы также можете написать:
const int * const buffer = (const int[]){ 0xF0 };
или
const int * const buffer = (const int[1]){ 0xF0 };
или
const int * const buffer = &(const int){ 0xF0 };
Обратите внимание, что порядок ключевых слов const
и int
не имеет значения, и, возможно, будет удобнее поместить ключевое слово const
ближе к *
, к которому оно относится:
int const * const buffer = (int const []) { 0xF0 };
Вопрос в следующем: зачем вообще нужен указатель? Если указатель постоянен, его нельзя изменить, чтобы он указывал на что-то другое, поэтому зачем определять указатель, если можно передать &data
напрямую?
Удаление квалификатора const
для вызовов функций является признаком недостатков проектирования: функция, принимающая указатель на данные, которые она не изменяет, должна иметь аргумент, определенный как whatevertype const *arg
, и вам не нужно никакого приведения при передаче адреса данных, будь то const
квалифицирован или нет. Если функция изменяет данные, на которые она получает указатель, передача ей данных, определенных как const
, вызовет неопределенное поведение при изменении, поскольку данные могут находиться в памяти только для чтения.
Вам действительно нужна переменная
buffer
? Почему бы не использовать&data
, если вы в противном случае используетеbuffer
?