Как просить "по крайней мере" размер int в C

Ситуация:

У меня есть приложение, написанное на C, которое является ресурсоемким и предназначено для переносимости. Я хочу разрешить компилятору выбирать самый быстрый размер int для архитектуры, если он составляет не менее 32 бит.

Можно ли выбрать размер "по крайней мере" 32 бита, или компилятор будет оптимизировать такие вещи из меня автоматически?

Ответ 1

Стандартный заголовок stdint.h предоставляет типы int_leastN_t и uint_leastN_t, где N - 8, 16, 32 и 64 (и, возможно, другие, но они не требуются). Они являются стандартными с C99.

Он также предоставляет "быстрые" альтернативы, ака int_fastN_t и uint_fastN_t, с теми же значениями N.

Итак, в вашем случае вы можете использовать int_least32_t или int_fast32_t.

Ответ 2

Как отмечали другие, стандартные файлы включают файлы int_fast32_t, int_least32_t, uint_fast32_t, uint_least32_t, которые, вероятно, будут вести себя так, как вы хотите, но такие типы должны использоваться с особой осторожностью. Из-за целочисленных правил продвижения, нет кода для кода C, чтобы избежать использования типов int и unsigned int. Кроме того, целые литералы не всегда могут быть из тех, которые ожидаются. Например, сравнение между int_fast32_t и литералами 0xABCD1234 или 12345u может выполняться как с подписью, так и без знака, в зависимости от того, является ли int 16, 32 или 64 бит. Аналогично, если n составляет 32 бит или больше, значение n &= ~0x8000; будет отличаться на 16-разрядной машине от более крупного.

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

Ответ 3

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

Требования

  • Тип списка, названный list здесь.
  • Метафокусировка, похожая на Haskell filter.
  • A head metafunction, чтобы получить первый элемент списка типов.

Код

Это решение автоматизирует принятое решение (это просто "перейдите к stdint.h и выберите наиболее подходящий для вас" ). Эта работа может быть выполнена компилятором, не так ли?

Сначала перечислите все наиболее специфичные для платформы самые быстрые целые типы, объявленные в <cstdint>:

using integer_types = list<std::int_fast8_t,std::int_fast16_t,
                           std::int_fast32_t,std::int_fast64_t>;

Обратите внимание, что список сортируется путем увеличения целочисленного размера.
Теперь определим предикат фильтрации. В нашем случае размер должен быть меньше размера, указанного пользователем (name it SIZE):

template<typename T>
using f = std::integral_constant<bool,sizeof(T)*CHAR_BITS <= SIZE>;

И затем отфильтруйте список целых типов и получите первый элемент результата:

using best_integer_t = head<filter<f,integer_types>>;

Суммированное решение

template<std::size_t SIZE>
struct fastest_integer_impl
{
    //Guard for the case the user specified less than one byte size:
    static constexpr const std::size_t size = SIZE >= CHAR_BITS ? size : CHAR_BITS;

    using integer_types = list<std::int_fast8_t,std::int_fast16_t,
                               std::int_fast32_t,std::int_fast64_t>;

    template<typename T>
    using f = std::integral_constant<bool,sizeof(T)*CHAR_BITS <= size>;

    using type = head<filter<f,integer_types>>;
};

template<std::size_t SIZE>
using fastest_integer = typename fastest_integer_impl<SIZE>::type;

Ответ 4

fastest = > согласовать с архитектурой, используя pragma pack. Без этого, если память не выровнена, для этого потребуется более одного доступа к памяти.

min 32 = > использовать int specifier - достаточно. Это гарантирует мне 32 бита в Linux по всем архитектурам.