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

Использование uint8, uint16 и т.д.

В настоящее время я работаю с базой кода (C, С++ mixed), предназначенной для 32-битной платформы MIPS. Процессор довольно современный (просто отметим, что у нас есть достаточная вычислительная мощность и память).

В базе кода используются такие типы данных, как uint8 [целое число без знака 1 байта], uint16 [целое беззнаковое целое число в 2 байта], uint32 [4-байтное беззнаковое целое число] и т.д.

Я знаю, как использование этих конструкций полезно при переносе кода на разные платформы.

Мои вопросы:

  • Какая польза от использования uint16, где uint32 также будет достаточным (если есть)?

  • Будет ли экономия на использовании памяти при использовании более коротких типов данных (с учетом выравнивания данных)?

  • Если нужно сохранить несколько байт памяти, нужно ли это сделать в современном оборудовании?

4b9b3361

Ответ 1

В чем польза/польза от использования uint16, где также будет достаточно uint32 (если есть)?

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

Протоколы данных и форматы файлов могут использовать uint16s, и может быть неправильным использование uint32s. Это зависит от формата и семантики (например, если вам нужны значения для обхода от 65535 до 0, uint16 будет делать это автоматически, а uint32 не будет).

OTOH, если те uint16s являются единственными локальными или глобальными переменными, замена их на 32-разрядные может не иметь существенной разницы, поскольку они могут занимать одно и то же пространство из-за выравнивания, и они передаются как 32-разрядные (в стеке или в регистре) на MIPS в любом случае.

Будет ли экономия на использовании памяти при использовании более коротких типов данных (с учетом выравнивания данных)?

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

Если нужно сохранить несколько байтов памяти, нужно ли это сделать в современном оборудовании?

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

Ответ 2

Прежде всего, если у вас есть такие типы, как uint16, где они определены? Они не являются стандартными типами, поэтому они будут определены в каком-то собственном заголовке - возможно, ваши или могут быть предоставлены какой-либо сторонней библиотекой; в этом случае вы должны спросить себя, насколько переносимым этот код, и создаете ли вы зависимость, которая может не иметь смысла в каком-либо другом приложении.

Другая проблема заключается в том, что многие библиотеки (с недобросовестной ИМО) определяют такие типы с различными именами, такими как UINT16, uint16, U16 UI16 и т.д., что он становится скорее кошмаром, гарантирующим соглашение типа и избегающим конфликтов имен. Если такие имена определены, они должны идеально размещаться в пространстве имен или иметь определенный префикс библиотеки, чтобы указать, какую библиотеку они были определены для использования, например rtos::uint16 - rtos_uint16.

Так как стандартная библиотека ISO C99 предоставляет стандартные типы длины бит в stdint.h, вы должны предпочесть их использование над любыми, определенными в проприетарном или стороннем заголовке. Эти типы имеют суффикс _t, например. uint16_t. В С++ они могут быть помещены в пространство имен std:: (хотя это не задано, поскольку заголовок был введен в C99).

1] Какая польза от использования uint16, где uint32 также будет достаточным (если есть)?

Помимо моих более ранних советов о предпочтении stdint.h uint16_t, существуют как минимум две законные причины использования специфичных для длины типов:

  • Для соответствия определенной ширине регистра оборудования.
  • Чтобы обеспечить общий и совместимый API для разных архитектур.

2] Будет ли экономия на использовании памяти при использовании более коротких типов данных (с учетом выравнивания данных)?

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

3] Если нужно сохранить несколько байтов памяти, нужно ли это сделать в современном оборудовании?

См. [2]. "Современное оборудование", однако, не обязательно подразумевает большие ресурсы; существует множество 32-битных устройств ARM Cortex-M с использованием всего лишь нескольких Кбайт ОЗУ. Это больше касается свободного пространства, затрат и энергопотребления, чем для дизайна или архитектуры.

Ответ 3

cstdint имеет множество typedef для разных целей.

  • intN_t для определенной ширины
  • int_fastN_t для самого быстрого целого числа, которое имеет не менее N бит
  • int_leastN_t для наименьшего целого числа, имеющего не менее N бит
  • Их эквиваленты unsigned

Вы должны выбрать в зависимости от ваших обстоятельств. Хранение тысяч в std::vector и не выполнение множества вычислений? intN_t, вероятно, ваш человек. Нужно быстро вычислить небольшое число целых чисел? int_fastN_t, вероятно, ваш парень.

Ответ 4

Отв. 1. Программное обеспечение имеет определенные требования и спецификации, которые строго требуют принимать только 8/16-бит параметра при кодировании/декодировании или некоторых других определенных целях. Таким образом, даже если вы присваиваете значение более 127 в u8, оно автоматически обрезает данные для вас.

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

Отв. 3. Разумеется, экономия памяти имеет смысл в современных h/w.

Ответ 5

Использование uint16_t вместо uint32_t - сохранение памяти. Это может быть также аппаратное ограничение (например, какой-то периферийный контроллер действительно отправляет 16 бит!) Однако, это может не стоить использовать его из-за соображений кэширования и выравнивания (вам действительно нужно проверить).

Ответ 6

В чем польза/польза от использования uint16, где также будет достаточно uint32 (если есть)?

Существуют процессоры, где unsigned char - 16-разрядное значение. Единичное тестирование такого кода было бы трудным без использования typedefs (uint16 - это просто typedef для соответствующего типа).

Кроме того, с использованием этих typedefs легче создавать на разных платформах без особых проблем.

Будет ли экономия на использовании памяти при использовании более коротких типов данных (с учетом выравнивания данных)?

Нет, это не вопрос. Если uint16 является typedef для unsigned short, вы можете использовать unsigned short всюду, но вы можете получать разные типы на разных платформах.

Конечно, использование меньшего типа уменьшит потребление памяти. Например, используя uint16 вместо uint32, но только если вы используете массивы.

Если нужно сохранить несколько байтов памяти, нужно ли это сделать в современном оборудовании?

Это зависит от платформы:

  • меньше использования памяти означает меньше промахов в кеше
  • Если поддерживается, есть SIMD-функции, которые обрабатывают 16-разрядные данные.

Ответ 7

Ответы на ваши вопросы сводятся к одной ключевой концепции: насколько велики данные? Если вы много хрустаете, то преимущество использования меньших типов данных очевидно. Подумайте об этом так: простое вычисление недавно открытого большинства известных премьер может привести вас к нехватке памяти на обычной рабочей станции. Само по себе номер стоит выше гигабайта только для хранения. Это не включает работу по вычислению фактического числа. Если бы вы использовали толстый тип данных вместо тонкого, вы можете посмотреть на два гигабайта вместо этого. Простейший пример, но хороший, тем не менее.

Ответ 8

Использование целочисленных типов точной ширины, таких как int32_t и друзей, полезно избегать ошибок расширений знака между платформами, которые имеют разные размеры для int и long. Это может произойти, например, при применении бит-масок или при смещении бит. Если вы выполняете эти операции на long, например, и ваш код работает для 32-разрядного long, он может разбиться на 64-разрядный long. Если, с другой стороны, вы используете uint32_t, вы точно знаете, какие результаты вы получите независимо от платформы.

Они также полезны для обмена двоичными данными между платформами, где вам нужно только беспокоиться о достоверности хранимых данных, а не о ширине бита; если вы пишете файл int64_t в файл, вы знаете, что на другой платформе вы можете его прочитать и сохранить в int64_t. Если вы пишете long вместо этого 64 бит на одной платформе, вам может понадобиться long long на другой платформе, потому что long всего 32 бита.

Сохранение памяти обычно не является причиной, если вы не говорите о очень ограниченных средах (встроенных материалах) или больших наборах данных (например, массив с 50 миллионами элементов или такой.)

Ответ 9

Необходимо проверить произведенный машинный код/​​ассемблер, чтобы убедиться в сохранности кода. В архитектуре типа RISC типичный немедленный 16-разрядный, но использование uint16_t в любом случае будет потреблять полный 32-разрядный регистр - таким образом, при использовании типов int, но использование значений вблизи нуля приведет к таким же результатам и будет более переносимым.

ИМО экономия памяти стоит на современных платформах. Более жесткий код приводит, например, к лучшее время автономной работы и более свободный UX. Тем не менее, я бы предложил микроуправление размером только при работе с (большими) массивами или когда переменная сопоставляется с каким-то реальным ресурсом HW.

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