Как сделать мои типы данных независимыми от компилятора в C
Я изучал UC/OS и прочитал эту статью:
Поскольку разные микропроцессоры имеют разную длину слова, порт µC/OS-II включает в себя серию определений типов, обеспечивающих переносимость. В частности, код µC/OS-II никогда не использует типы данных C short, int и, long, поскольку они по своей природе являются непереносимой. Вместо этого я определил целочисленные типы данных, которые являются переносимыми и интуитивно понятными, как показано в листинге 1.1. Кроме того, для удобства я включил типы данных с плавающей запятой, хотя µC/OS-II не использует с плавающей запятой. Ниже приведен листинг 1.1
typedef unsigned char BOOLEAN;
typedef unsigned char INT8U;
typedef signed char INT8S;
typedef unsigned int INT16U;
typedef signed int INT16S;
typedef unsigned long INT32U;
typedef signed long INT32S;
typedef float FP32;
typedef double FP64;
#define BYTE INT8S
#define UBYTE INT8U
#define WORD INT16S
#define UWORD INT16U
#define LONG INT32S
#define ULONG INT32U
Мои вопросы:
1- Что автор имеет в виду под длиной слова (первые жирные слова в моем теле вопроса)?!
2- Почему короткие типы данных int и long по своей природе непереносимы.
3- это typedef
такое микропроцессорная директива, и если она есть, какова ее функция?!
4- Могу ли я написать typedef unsigned char (anything)
вместо typedef unsigned char INT8U;
5- Почему авторский код typedef unsigned char INT8U;
а потом #define UBYTE INT8U
я не могу использовать это напрямую typedef unsigned char UBYTE;
6- Существует двойное использование typedef unsigned char
один из них является typedef unsigned char INT8U;
и другие typedef unsigned char BOOLEAN;
Почему он это сделал?!
1 ответ
1- Что автор имеет в виду под длиной слова
Слово - это фундаментальная единица памяти, такая как страница - на самом деле есть статья о слове, которую я не буду извергать. Как говорит ваш автор, значение для C состоит в том, что он не всегда один и тот же, но определяется характеристиками оборудования. Возможно, это одна из причин, по которой стандарт C не определяет буквальный размер основных типов; наиболее очевидным для рассмотрения является размер указателей, который будет 4 байта в 32-разрядных системах и 8 в 64-разрядных системах, чтобы отразить размер адресного пространства.
2- Почему короткие типы данных int и long по своей природе непереносимы.
Точнее: они такие же портативные, как C, но их размер не стандартизирован, что может сделать их бесполезными для многих приложений, где требуется фиксированный определенный размер.
3- Является ли typedef директивой микропроцессора, и если это так, какова ее функция?
Нет, это не директива процессора. Это хороший кусок синтаксического сахара, который позволяет вам определять пользовательские типы.
4- Могу ли я написать typedef unsigned char (что угодно) вместо typedef unsigned char INT8U;
Да, это идея. Остерегайтесь, что стандарт C даже не определяет размер символа, хотя я никогда не слышал о реализации, где это что-то кроме 8-битных [но кто-то в комментариях имеет].
5- Почему автор кода typedef unsigned char INT8U; а затем #define UBYTE INT8U я не могу использовать это напрямую typedef unsigned char UBYTE;
Вы могли бы, да. Возможно, автор хотел ограничить количество мест, где этот тип определен. Так как с помощью #define
является директивой препроцессора, она также может слегка оптимизировать исполняемый файл (хотя и не до такой степени, которая может считаться в целом значимой).
6- Существует двойное использование typedef unsigned char, один из которых - typedef unsigned char INT8U; и другой typedef без знака char BOOLEAN; Почему он это сделал?!
Опять же, использование typedefs очень много о "сахаре"; они могут сделать ваш код чище, проще для чтения и (при условии, что все сделано правильно), более надежным. "Boolean" - это математический термин CS для типа, который имеет только два значащих значения: ноль (false) или не ноль (true). Таким образом, теоретически это может быть реализовано с помощью всего одного бита, но это ни просто, ни, в конечном счете, эффективно (поскольку нет процессоров с 1-битными регистрами, им бы в любом случае пришлось бы нарезать кубики и подделать их). Определение типа "bool" или "логический" типично в C и используется для указания того, что значение значения является либо истинным, либо ложным - оно хорошо работает, например: if (var)
(правда) и if (!var)
(false), поскольку C уже оценивает этот путь (0 и NULL - единственные значения, которые будут проходить if (!var)
). В то время как использование чего-то вроде INT8U
означает, что вы имеете дело со значением в диапазоне от десятичного 0 до 255, так как оно без знака. Я думаю, что положить U
upfront is a more common practice (UINT8
), but if you are used to the concepts it is reasonably clear. And of course the typedef/define is not hard to check.
Около stdint.h
Integer types are the ones with the greatest range of variation, and in fact the ISO C standard does require that an implementation include definitions for various integer types with certain minimum sizes in stdint.h
, These have names like int_least8_t
, Of course, types with a real fixed size (not just a minimum) are needed for many things, and most common implementations do provide them. The C99 standard dictates that if they are available, they should be accessible via names following the pattern intN_t
(подписано) и uintN_t
(unsigned), where N
is the number of bits. The signed types are also specified as two's complement, so one can work with such values in all kinds of highly portable ways.
As a final note, while I'm not familiar with MicroC, I would not take that documentation as representative of C generally -- it is intended for use in a somewhat restrictive and specialized environment (a 16-bit int, implied by the typedefs, is unusual, and so if you ran that code elsewhere, INT16U could be 32-bits, etc). I'd guess MicroC only conforms to ANSI C, which is the oldest and most minimal standard; evidently it has no stdint.h.