Подтвердить что ты не робот

Когда следует использовать абстракцию типа во встроенных системах

Я работал над несколькими встроенными системами. Все они использовали typedef (или #defines) для таких типов, как UINT32.

Это хорошая методика, поскольку она приводит к увеличению размера типа для программиста и делает вас более осведомленным о возможностях переполнения и т.д.

Но на некоторых системах вы знаете, что компилятор и процессор не будут меняться в течение всего жизненного цикла проекта.

Итак, что должно повлиять на ваше решение о создании и применении конкретных проектов?

ИЗМЕНИТЬ Я думаю, мне удалось потерять суть моего вопроса, и, возможно, это действительно два.

При встроенном программировании вам могут потребоваться типы определенного размера для интерфейсов, а также для работы с ограниченными ресурсами, такими как оперативная память. Этого нельзя избежать, но вы можете использовать основные типы из компилятора.

Для всего остального типы имеют меньшее значение.
Вы должны быть осторожны, чтобы не вызвать переполнение и, возможно, потребуется следить за использованием регистров и стека. Это может привести вас к UINT16, UCHAR. Использование типов, таких как UCHAR, может добавить "пушок" компилятора. Поскольку регистры обычно больше, некоторые компиляторы могут добавить код, чтобы заставить результат в тип.

 я ++;
может стать
 ADD REG, 1
И REG, 0xFF
что не требуется.

Итак, я думаю, что мой вопрос должен был быть: -

учитывая ограничения встроенного программного обеспечения, что является лучшей политикой для проекта, в котором будет работать много людей, не все из которых будут иметь одинаковый уровень опыта.

4b9b3361

Ответ 1

Я использую абстракцию типа очень редко. Вот мои аргументы, отсортированные в порядке возрастания субъективности:

  • Локальные переменные отличаются от элементов структуры и массивов в том смысле, что вы хотите, чтобы они соответствовали регистру. Локальный int16_t с 32-битным/64b-кодом может сделать код медленнее по сравнению с локальным int, поскольку компилятору придется добавлять операции /force/overflow в соответствии с семантикой int16_t. В то время как C99 определяет intfast_t typedef, AFAIK, простой int также будет вписываться в регистр, и это, несомненно, более короткое имя.

  • Организации, которые, подобно этим typedefs, почти всегда заканчивают несколькими из них (INT32, int32_t, INT32_T, ad infinitum). Таким образом, организации, использующие встроенные типы, лучше, в некотором смысле, имея только один набор имен. Я хотел бы, чтобы люди использовали typedefs из stdint.h или windows.h или что-то существующее; и когда у мишени нет этого файла .h, насколько сложно добавить его?

  • Типефы могут теоретически помочь переносимости, но я, например, никогда не получал от них ничего. Есть ли полезная система, которую вы можете перенести с 32b на 16b? Есть ли 16-битная система, которая не является тривиальной для переноса на 32-битную цель? Более того, если большинство vars являются ints, вы действительно получите что-то из 32 бит в новой цели, но если они int16_t, вы не будете. И места, которые трудно переносить, в любом случае требуют ручного осмотра; прежде чем вы попробуете порт, вы не знаете, где они находятся. Теперь, если кто-то считает, что так легко переносить вещи, если у вас есть typedefs повсюду - когда приходит время на порт, который случается с несколькими системами, напишите script, преобразуя все имена в базу кода. Это должно работать в соответствии с логикой "без ручного контроля", и она откладывает усилия до момента, когда это действительно дает выгоду.

  • Теперь, если переносимость может быть теоретической выгодой от typedefs, удобочитаемость обязательно сходит с ума. Просто посмотрите на stdint.h: {int,uint}{max,fast,least}{8,16,32,64}_t. Много типов. Программа имеет множество переменных; действительно ли это легко понять, что должно быть int_fast16_t и которое должно быть uint_least32_t? Сколько раз мы молча переключаемся между ними, делая их совершенно бессмысленными? (Мне особенно нравятся преобразования BOOL/Bool/eBool/boolean/bool/int. Каждая программа, написанная упорядоченной организацией с мандатом typedefs, усеяна этим).

  • Конечно, в С++ мы могли бы сделать систему типов более строгой, обернув числа в экземплярах класса шаблонов с перегруженными операторами и т.д. Это означает, что теперь вы получите сообщения об ошибках формы "class Number < int, Least, 32 > не имеет оператора + перегрузка для аргумента типа class Number < unsigned long long, Fast, 64 > , кандидаты..." я не называйте эту "удобочитаемость". Ваши шансы на реализацию этих классов-оболочек правильно микроскопичны, и большую часть времени вы будете ждать, когда будут созданы компиляции бесчисленных экземпляров.

Ответ 2

В стандарте C99 имеется ряд стандартных размеров. Если вы можете использовать компилятор, который поддерживает C99 (gcc), вы найдете их в <stdint.h>, и вы можете просто использовать их в своих проектах.

Кроме того, во встроенных проектах может быть особенно важно использовать типы как своего рода "защитную сетку" для таких вещей, как конверсии единиц. Если вы можете использовать С++, я понимаю, что есть некоторые "единичные" библиотеки, которые позволяют вам работать в физических единицах, которые определяются системой типов С++ (через шаблоны), которые скомпилированы как операции над базовыми типами скаляров. Например, эти библиотеки не позволят вам добавить distance_t в mass_t, потому что блоки не выстраиваются в линию; вы действительно получите ошибку компилятора.

Даже если вы не можете работать на С++ или на другом языке, который позволяет вам писать код таким образом, вы можете, по крайней мере, использовать систему типа C, чтобы помочь вам поймать подобные ошибки. (Это было на самом деле оригинальным намерением венгерской нотации Simonyi.) Просто потому, что компилятор не будет кричать на вас, чтобы добавить meter_t в gram_t, не означает, что вы не должны использовать такие типы. Кодовые обзоры будут намного более эффективными при обнаружении ошибок блока.

Ответ 3

Мое мнение, если вы в зависимости от минимального/максимального/определенного размера не, просто предположите, что (скажем) unsigned int - 32 байта - вместо этого используйте uint32_t (при условии, что ваш компилятор поддерживает C99).

Ответ 4

Мне нравится использовать типы stdint.h для определения системных API специально, потому что они явно говорят, как большие элементы. В прежние времена Palm OS системные API были определены с помощью путастых стильных типов, таких как "Word" и "SWord", которые были унаследованы от очень классической Mac OS. Они сделали очистку, вместо этого сказали Int16, и это упростило API для новичков, особенно с странными 16-разрядными указателями на эту систему. Когда они разрабатывали Palm OS Cobalt, они снова сменяли эти имена, чтобы соответствовать именам stdint.h, делая их еще более ясными и уменьшая количество typedef, которым они должны были управлять.

Ответ 5

Я считаю, что стандарты MISRA предлагают (требуют?) использование typedefs.

С личной точки зрения использование typedefs не оставляет путаницы в отношении размера (в битах/байтах) определенных типов. Я видел, как ведущие разработчики пытаются использовать оба способа разработки, используя стандартные типы, например. int и использование пользовательских типов, например. UInt32.

Если код не переносится, мало пользы от использования typedefs, однако, если я, как я, тогда вы работаете над обоими типами программного обеспечения (переносная и фиксированная среда), тогда может быть полезно сохранить стандарт и использовать вырезанные типы. По крайней мере, как вы говорите, программист тогда очень хорошо знает, сколько памяти они используют. Еще один фактор, который следует учитывать, - как вы уверены, что код не будет перенесен в другую среду? Я видел, что конкретный код процессора необходимо перевести, поскольку аппаратный инженер внезапно должен был изменить плату, это не очень хорошая ситуация, но из-за пользовательских typedefs это могло быть намного хуже!

Ответ 6

Консистенция, удобство и удобочитаемость. "UINT32" гораздо читабельнее и записывается, чем "unsigned long long", что эквивалентно для некоторых систем.

Кроме того, компилятор и процессор могут быть исправлены для жизни проекта, но код из этого проекта может найти новую жизнь в другом проекте. В этом случае очень удобны согласованные типы данных.

Ответ 7

Если ваши встроенные системы - это как-то критически важная система безопасности (или аналогичная), она настоятельно рекомендовала (если не требуется) использовать typedefs над обычными типами.

Как TK. сказал, что MISRA-C имеет (консультативное) правило:

Правило 6.3 (консультативное): typedefs, которые указывают размер и подпись, должны использоваться вместо основных числовых типов.

(из MISRA-C 2004, это правило № 13 (adv) MISRA-C 1998)


То же самое относится и к С++ в этой области; например. Стандарты кодирования JSF С++:

Правило AVA 209 Будет создан файл UniversalTypes для определения всех sta ndard для разработчиков. Типы включают в себя: [uint16, int16, uint32_t и т.д.]

Ответ 8

Использование <stdint.h> делает ваш код более переносимым для модульного тестирования на ПК.

Он может сильно укусить вас, когда у вас есть тесты на все, но он все равно ломается в вашей целевой системе, потому что int внезапно достигает только 16 бит.

Ответ 9

Возможно, я странный, но я использую ub, ui, ul, sb, si и sl для своих целых типов. Возможно, "i" для 16 бит кажется немного устаревшим, но мне нравится внешний вид ui/si лучше, чем uw/sw.