Я унаследовал некоторый старый код, который предполагает, что int
может хранить значения от -2 31 до 2 ^ 31 -1, это переполнение просто оборачивается, ичто знаковый бит является старшим битом.Другими словами, этот код должен был использовать uint32_t
, за исключением того, что это не так.Я хотел бы исправить этот код для использования uint32_t
.
Сложность заключается в том, что код распространяется в виде исходного кода, и мне не разрешено изменять внешний интерфейс.У меня есть функция, которая работает с массивом int
.То, что он делает внутри, это его собственный бизнес, но в интерфейсе отображается int
.В двух словах, интерфейс выглядит так:
struct data {
int a[10];
};
void frobnicate(struct data *param);
Я хотел бы изменить int a[10]
на uint32_t a[10]
, но мне не разрешено изменять определение struct data
.
Я могу заставить код работать на uint32_t
или unsigned
внутри:
struct internal_data {
unsigned a[10];
};
void frobnicate(struct data *param) {
struct internal_data *internal = (struct internal_data *)param;
// ... work with internal ...
}
Однако на самом деле это не правильно C, так как он преобразует указатели в разные типы.
Isесть ли способ добавить защиту во время компиляции, чтобы для тех редких людей, для которых int
не является 32-битной «старой школой», код не создавался?Если int
меньше 32 бит, код все равно никогда не работал.Для подавляющего большинства пользователей код должен собираться так, чтобы компилятор не делал «странных» вещей с переполнением int
вычислений.
Я распространяю исходный код, и люди могут его использоватьс любым компилятором, который они выберут, поэтому специфичные для компилятора приемы не имеют значения.
Я по крайней мере собираюсь добавить
#if INT_MIN + 1 != -0x7fffffff
#error "This code only works with 32-bit two's complement int"
#endif
С этим защитником, что может пойти не так с приведенным выше приведением?Есть ли надежный способ манипулировать массивом int
, как если бы его элементы были unsigned
, без копирования массива?
В итоге:
- Я не могу изменитьпрототип функции.Он ссылается на массив
int
. - Код должен манипулировать массивом (не копией массива) как массивом
unsigned
. - Код должен создаваться на платформах, гдеон работал раньше (по крайней мере, с достаточно дружественными компиляторами) и не должен собираться на платформах, где он не может работать.
- Я не могу контролировать, какой компилятор используется и с какими настройками.