Я ищу способ надежно определить, компилируется ли код C ++ в 32 против 64 бит. Мы придумали то, что мы считаем разумным решением с использованием макросов, но нам было любопытно узнать, могут ли люди подумать о случаях, когда это может дать сбой, или есть лучший способ сделать это. Обратите внимание, что мы пытаемся сделать это в кросс-платформенной среде с несколькими компиляторами.
#if ((ULONG_MAX) == (UINT_MAX))
# define IS32BIT
#else
# define IS64BIT
#endif
#ifdef IS64BIT
DoMy64BitOperation()
#else
DoMy32BitOperation()
#endif
Спасибо.
c++
32bit-64bit
conditional-compilation
Джо Коркери
источник
источник
stdint.h
может быть вашим другом, или вам может потребоваться разработать некоторые собственные typedefs самостоятельно.Ответы:
К сожалению, нет кроссплатформенного макроса, который бы определял 32/64 бит в основных компиляторах. Я нашел самый эффективный способ сделать это следующим образом.
Сначала я выбираю свое собственное представление. Я предпочитаю ENVIRONMENT64 / ENVIRONMENT32. Затем я выясняю, что все основные компиляторы используют для определения, является ли это 64-битной средой или нет, и использую это для установки моих переменных.
Другой более простой способ - просто установить эти переменные из командной строки компилятора.
источник
#if _WIN32 || _WIN64
...#elif __GNUC__
...#else
# error "Missing feature-test macro for 32/64-bit on this compiler."
?источник
size_t
достаточно велик, чтобы вместить размер любого выделенного объекта в системе. Обычно это то, что вы хотите знать при условной компиляции. Если это не то, что вы хотите, вы можете использовать этот фрагмент с другим типом вместоsize_t
. Например, это может бытьvoid*
.К сожалению, в кросс-платформенной среде кросс-компиляции не существует единого надежного способа сделать это исключительно во время компиляции.
Поэтому единственный надежный метод - это объединить 3 простых проверки :
Простая проверка 1/3: настройка времени компиляции
Выберите любой метод для установки требуемой переменной #define. Я предлагаю метод от @JaredPar:
Простая проверка 2/3: проверка во время выполнения
В main () дважды проверьте, имеет ли sizeof () смысл:
Простая проверка 3/3: надежная проверка времени компиляции
Общее правило: «каждый #define должен заканчиваться на #else, который генерирует ошибку».
Обновление 2017-01-17
Комментарий от
@AI.G
:Приложение
Кстати, приведенные выше правила могут быть адаптированы, чтобы сделать всю вашу кодовую базу более надежной:
Причина того, что это работает хорошо, заключается в том, что он заставляет вас заранее думать о каждом отдельном случае, а не полагаться на (иногда ошибочную) логику в части «else» для выполнения правильного кода.
Я использовал эту технику (среди многих других), чтобы написать 30-тысячный линейный проект, который работал безупречно со дня, когда он был впервые запущен в производство (это было 12 месяцев назад).
источник
sizeof(void*)
это решается во время компиляции или во время выполнения? если это во время компиляции, то во время выполнения проверка всегда будетif(8!=8){...}
.static_assert(sizeof(void*) == 4);
. Теперь все это делается во время компиляции :)static_assert(sizeof(void*) * CHAR_BIT == 32)
более выразителен и технически корректен (хотя я не знаю ни одной архитектуры, где байты имеют разное количество битов, чем 8)Вы должны быть в состоянии использовать макросы, определенные в
stdint.h
. В частностиINTPTR_MAX
, именно то значение, которое вам нужно.Некоторые (все?) Версии компилятора Microsoft не входят в комплект
stdint.h
. Не знаю почему, так как это стандартный файл. Вот версия, которую вы можете использовать:http://msinttypes.googlecode.com/svn/trunk/stdint.hисточник
<stdint.h>
и<cstdint>
. Что касается нынешнего положения вещей - библиотека VC ++ происходит из Dinkumware (все еще делает - TR1 также была взята оттуда), но из того, что я помню, читая в VCBlog, она подвергается довольно значительному рефакторингу для аккуратной компиляции/clr
, работы со всеми MSVC нестандартные типы, такие как__int64
, и так далее - вот почему это не так просто, как просто взять и поместить в следующую версию компилятора.Это не будет работать на Windows для начала. Long и int являются 32-битными, независимо от того, компилируете ли вы для 32-битных или 64-битных окон. Я думаю, что проверка размера указателя 8 байт, вероятно, является более надежным маршрутом.
источник
sizeof(void*) == 8 ? Do64Bit() : Do32Bit();
. Это может все еще оставить неиспользуемую функцию в двоичном файле, но выражение, скорее всего, скомпилировано только для вызова «правильной» функции.template<int> struct Thing; template<> struct Thing<4> { typedef uint32_t type; }; template<> struct Thing<8> { typedef uint64_t type; }; typedef Thing<sizeof(void*)>::type thingtype;
Вы могли бы сделать это:
источник
источник
«Скомпилировано в 64 бит» не очень хорошо определено в C ++.
C ++ устанавливает только нижние пределы для таких размеров, как int, long и
void *
. Нет гарантии, что int является 64-битным, даже если он скомпилирован для 64-битной платформы. Модель позволяет, например, 23 битint
с иsizeof(int *) != sizeof(char *)
Существуют разные модели программирования для 64-битных платформ.
Ваш лучший выбор - тест для конкретной платформы. Ваше второе лучшее портативное решение должно быть более конкретным в том, что является 64-битным.
источник
Ваш подход не был слишком далеко, но вы только проверяете ли
long
иint
одного и того же размера. Теоретически они могут быть 64-битными, и в этом случае ваша проверка не будет выполнена, предполагая, что оба будут 32-битными. Вот проверка, которая фактически проверяет размер самих типов, а не их относительный размер:В принципе, вы можете сделать это для любого типа, для которого у вас есть системный макрос с максимальным значением.
Обратите внимание, что стандарт
long long
должен быть не менее 64 бит даже в 32-битных системах.источник
#include <limits.h>
то перед#if
тестами.Люди уже предложили методы, которые попытаются определить, компилируется ли программа в
32-bit
или64-bit
.И я хочу добавить, что вы можете использовать функцию c ++ 11,
static_assert
чтобы убедиться, что архитектура соответствует вашим ожиданиям («расслабиться»).Итак, в месте, где вы определяете макросы:
источник
static_assert(sizeof(void*) * CHAR_BIT == 32)
является более выразительным и технически правильным (хотя я не знаю ни одной архитектуры, где байты имеют разное количество битов, чем 8)Приведенный ниже код отлично работает для большинства современных сред:
источник
_WIN64
требует , чтобы вы уже включили<windows.h>
. С помощью Visual C ++, то лучше использовать встроенный компилятор устанавливает:_M_IX86
,_M_X64
,_M_ARM
,_M_ARM64
и т.д.__ppc64__
,__powerpc64__
и_ARCH_PPC64
. Это ловит AIX и другие платформы тоже.Если вы можете использовать конфигурации проекта во всех своих средах, это упростит определение 64- и 32-разрядного символа. Таким образом, у вас будут такие конфигурации проекта:
32-битная отладка
32-разрядная версия
64-разрядная отладка
64-разрядная версия
РЕДАКТИРОВАТЬ: это общие конфигурации, а не целевые конфигурации. Называй их как хочешь.
Если ты не можешь сделать это, мне нравится идея Джареда.
источник
Я помещал 32-битные и 64-битные источники в разные файлы, а затем выбирал подходящие исходные файлы, используя систему сборки.
источник
-DBUILD_64BIT
. Часто некоторые вещи очень похожи как на 32-, так и на 64-битные, поэтому иметь его в одном файле может быть довольно практичным.Заимствования из репорт «s отличного ответа выше , и сочетая его с„ Лучше Макросами, Better Flags “из Fluent C ++, вы можете сделать:
Тогда вы можете использовать его как:
Или используя дополнительный макрос, который я добавил:
источник
Я добавляю этот ответ в качестве варианта использования и завершаю пример проверки выполнения, описанной в другом ответе. .
Это подход, который я использовал для передачи конечному пользователю, была ли программа скомпилирована как 64-битная или 32-битная (или другая, если на то пошло):
version.h
test.cc
Компилировать и тестировать
источник