Смешивание typedefs и определений для принудительного определения размеров типов данных - PullRequest
2 голосов
/ 26 октября 2011

Я занимаюсь модульным тестированием кода, написанного для другой платформы, и у меня возникла проблема, когда мне нужно ограничить размеры типов данных в тестируемом модуле. Поскольку я не могу напрямую изменить файл модуля, я подумал об использовании stdint.h typedefs и заменил объявление модулей с помощью define. По сути это:

#include <stdint.h>
#define int int16_t

int main() {
    uint16_t ui = 2;
    unsigned int uii = 3;
    printf("Hello\n");
    printf("Test %d, %d\n", ui, uii);
    return 0;
}

Однако с этим сообщением ничего не получится:

error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘uii’

Есть ли другой способ сделать такой тип замены?

Ответы [ 3 ]

3 голосов
/ 26 октября 2011

Почему ваш конкретный пример терпит неудачу, это потому, что он расширен до:

unsigned int16_t uii = 3;

, с которым модификатор unsigned явно не работает на int16_t.

Теперь, чтобы ответить на вопрос: Я не думаю, что вы можете сделать это, если у компилятора нет внутренней опции для изменения размера int.Попытка принудительно вызвать конфликт с внутренними библиотечными функциями.

Например: ваш printf() также сломается, потому что %d будет ожидать нормальное int, но вы передадите ему 16-битное целое.

РЕДАКТИРОВАТЬ: Этот пример printf() не является хорошим примером, поскольку int16_t будет повышен до int.Но общая идея все еще верна.(см. комментарии)

1 голос
/ 31 октября 2011

Модификаторы signed, unsigned, long, short могут применяться только к ключевым словам, обозначающим встроенные типы. Они не могут быть применены к типу имени, который является псевдонимом для встроенного типа: синтаксис C не позволяет этого.

Что касается того, что вы можете сделать, я думаю, что ответ Mysticial охватывает это. Изменение размера int будет конфликтовать с любым ABI, который компилятор использует для выполнения библиотечных и системных вызовов, поэтому вы не сможете сделать это без поддержки компилятора. Например, предположим, что у вас есть функция, объявленная следующим образом:

int foo(int a);

Если вы замените все упоминания int на short в TU, который вызывает эту функцию, но не в TU, который ее реализует, то вызывающая сторона передаст и получит short, тогда как реализация функции ожидает и возвращает int. Это не обязательно будет работать. Вам нужно, чтобы все библиотеки, включая стандартные библиотеки и любые системные вызовы, которые они делают, были скомпилированы так, чтобы вызывающий и вызываемый абоненты соглашались, что такое int.

Одним из вариантов, конечно, является изменение всего кода, который вы тестируете, использование макросов вместо int, unsigned int и так далее. Тогда любые объявления функций в заголовках оставляются в покое. Будут неявные преобразования, когда типы не будут совпадать, что может вызвать предупреждения компилятора и усекать значения, но, по крайней мере, имеет определенное поведение. По сути это внедрение зависимостей через препроцессор.

0 голосов
/ 26 октября 2011

Ключ должен использовать

# define int short

вместо.

...