Узнайте самый большой собственный целочисленный тип на текущей платформе
Проблема заключается в создании своего рода большой целочисленной библиотеки. Я хочу сделать это как кросс-платформу, так и как можно быстрее. Это означает, что я должен попытаться выполнить математику с такими же большими типами данных, которые поддерживаются в системе.
Я действительно не хочу знать, компилирую ли я для 32-битной или 64-битной системы; все, что мне нужно - это способ создания 64-битного или 32-битного или любого другого целого числа на основе того, что является самым большим доступным. Я буду использовать sizeof для того, чтобы вести себя по-разному в зависимости от того, что это такое.
Вот некоторые возможные решения и их проблемы:
Используйте sizeof (void *):
Это дает размер указателя на память. Возможно (хотя и маловероятно), что система может иметь более крупные указатели на память, чем способна выполнять математику с или наоборот.
Всегда используйте long:
Хотя верно, что на нескольких платформах длинные целые числа составляют 4 байта или 8 байтов в зависимости от архитектуры (моя система является одним из таких примеров), некоторые компиляторы реализуют длинные целые числа как 4 байта даже в 64-битных системах.
Всегда использовать длинный длинный:
На многих 32-разрядных системах это 64-битное целое число, которое может быть не таким эффективным (хотя, вероятно, более эффективным, чем любой код, который я могу писать). Настоящая проблема заключается в том, что она может вообще не поддерживаться на некоторых архитектурах (например, в том, что один из них поддерживает мой mp3-плеер).
Чтобы подчеркнуть, мой код не заботится о том, какой фактический размер целого числа когда-либо был выбран (он полагается на sizeof() для чего-либо, где имеет значение размер). Я просто хочу, чтобы он выбрал тип целого числа, что приведет к тому, что мой код будет наиболее эффективным.
Ответы
Ответ 1
Если вам действительно нужен тип нативного размера, я бы использовал size_t
, ptrdiff_t
или intptr_t
и uintptr_t
. В любой непатологической системе все это будет родной размер слова.
С другой стороны, есть преимущества в простоте, чтобы всегда работать с фиксированным размером, и в этом случае я бы просто использовал int32_t
или uint32_t
. Причина, по которой я говорю проще, состоит в том, что вам часто приходится знать такие вещи, как "наибольшая степень 10, которая подходит для типа" (для десятичного преобразования) и другие константы, которые не могут быть легко выражены как постоянные выражения в терминах типа вы использовали. Если вы просто выбираете фиксированное количество бит, вы также можете исправить удобные константы (например, 1000000000 в моем примере). Конечно, делая это таким образом, вы жертвуете некоторой производительностью в более высоких системах. Вы можете использовать противоположный подход и использовать больший фиксированный размер (64 бита), который был бы оптимальным для более высокопроизводительных систем, и предположим, что код компилятора для 64-разрядной арифметики на 32-битных машинах будет по меньшей мере так же быстро, как ваш код bignum обрабатывает 2 32-битных слова, и в этом случае он по-прежнему оптимален.
Ответ 2
Лучший способ - не полагаться на автоматическое обнаружение, а на целевые компиляторы с набором операторов #if/#else
выбрать тип, который вы протестировали, и знать, что он оптимален.
Ответ 3
Здесь как мы это сделали в bsdnt
#if ULONG_MAX == 4294967295U
typedef uint32_t word_t;
typedef unsigned int dword_t __attribute__((mode(DI)));
#define WORD_BITS 32
#else
typedef uint64_t word_t;
typedef unsigned int dword_t __attribute__((mode(TI)));
#define WORD_BITS 64
#endif
Если это интересно, парень, который инициировал проект, написал blog при написании библиотек bignum.
GMP/MPIR значительно сложнее; gmp-h.in становится gmp.h post-configure, который определяет это:
#define GMP_LIMB_BITS @[email protected]
Короче говоря, длина задается как часть процесса сборки, которая работает через config.guess
(т.е. autotools).
Ответ 4
Использование int_fast32_t из stdint.h представляется вариантом, хотя вы на милость тех, кто решает, что касается того, что "быстрая".