В функции C++ мне нужно, чтобы компилятор выбрал другой блок, если он компилируется для 64-битной архитектуры.
Я знаю способ сделать это для MSVC++ и g ++, поэтому опубликую его в качестве ответа. Однако я хотел бы знать, есть ли способ лучше (более элегантный, который работал бы для всех компиляторов / всех 64-битных архитектур). Если нет лучшего способа, какие еще предопределенные макросы мне следует искать, чтобы они были совместимы с другими компиляторами / архитектурами?





Это работает для MSVC++ и g++:
#if defined(_M_X64) || defined(__amd64__)
// code...
#endif
… Но не работает, если вы ориентируетесь на ARM64 или любую другую архитектуру.
Раймонд покрывает это.
Это специфично для Visual C++.
@rdb Первая часть, потом идет Если вы не хотите привязывать себя к конкретному компилятору, вам придется ...
Эта статья вводит в заблуждение и неверна! Попробуйте ifdef _X86_ в Visual Studio, ничего не добавляя.
@Pavel При всем уважении, вам нужно многому научиться, прежде чем вы сможете сказать, что статья Раймонда Чена вводит в заблуждение и неверна. Что касается _X86_, он прямо говорит: // assumes you use makefile.def [from the Windows DDK mentioned in the previous sentence], то есть где это определено.
@GSerg спасибо за указание, я только что прочитал его статью. Он совершенно прав, ваш ответ неверен и вводит в заблуждение.
Ссылка теперь не работает. Статья перенесена на devblogs.microsoft.com/oldnewthing/20060906-07/?p=29843
Вот хороший обзор Mac OS X:
http://developer.apple.com/documentation/Darwin/Conceptual/64bitPorting
Если вы компилируете для платформы Windows, вам следует использовать:
#ifdef _WIN64
Компилятор MSVC определяет это как для платформ x64, так и для платформ ia64 (вы же не хотите сокращать этот рынок, не так ли?). Я не уверен, что gcc делает то же самое, но должен, если нет.
Альтернативой является
#ifdef WIN64
в котором есть небольшая разница. WIN64 (без подчеркивания в начале) определяется SDK (или конфигурацией сборки). Поскольку это определяется конфигурацией SDK / build, она также должна работать с gcc.
#ifdef _LP64
Работает на обеих платформах
Но разве не Windows ILP64?
@CraigRinger Windows - это LLP64. По какой-то странной причине макрос все равно определен, что меня расстраивает.
Почему вы выбираете один блок другому? Если ваше решение основано на размере указателя, используйте sizeof(void*) == 8. Если ваше решение основано на размере целого числа, используйте sizeof(int) == 8.
Я считаю, что название самой архитектуры редко имеет какое-либо значение. Вы проверяете только то, что вам нужно проверить, для целей того, что вы собираетесь делать. Ваш вопрос не очень четко описывает, какова ваша цель проверки. То, что вы спрашиваете, похоже на попытку определить, установлен ли DirectX, путем запроса версии Windows. В вашем распоряжении более портативные и универсальные инструменты.
sizeof (int) - не лучший пример. Это зависит от компилятора. Я пробовал 64-битный Linux с g ++, и он был длиной 4 байта. Лучше использовать sizeof (void *), чтобы определить архитектор. Но я не уверен, что это одинаково на всех машинах.
@klew, я думаю, вы упустили точку зрения flodin: «Вы проверяете только то, что вам нужно проверить, для целей того, что вы собираетесь делать».
Но ни один из них не работает в препроцессоре, например. #if sizeof(int)==4 - поскольку препроцессор не разрешает sizeof в выражениях #if.
@greggo Вы можете использовать, например, INT_MAX вместо этого. См., Например, <cstdint>.
@klew Да, int всегда будет 32-битным независимо от архитектуры для обратной совместимости. int64_t (uint64_t для беззнакового) требуется для 64-битных чисел.
Цель проверки явно выходит за рамки вопроса. Неважно. Как бы «редко» ни была такая необходимость, по вашей оценке, случаи, когда она нужна, действительно существуют.
Если вы используете Windows, вам, вероятно, лучше получить переменную среды PROCESSOR_ARCHITECTURE из реестра, потому что sizeof (PVOID) будет равен 4, если это 32-битный процесс, работающий в 64-битной операционной системе (также известной как WOW64):
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SYSTEM\CurrentControlSet\Control\Session Manager\Environment"), 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
LPSTR szArch = new CHAR[100];
ZeroMemory(szArch, 100);
if (RegQueryValueEx(hKey, _T("PROCESSOR_ARCHITECTURE"), NULL, NULL, (LPBYTE)szArch, &dwSize) == ERROR_SUCCESS) {
if (strcmp(szArch, "AMD64") == 0)
this->nArchitecture = 64;
else
this->nArchitecture = 32;
} else {
this->nArchitecture = (sizeof(PVOID) == 4 ? 32 : 64);
}
RegCloseKey(hKey);
}
Это время выполнения. OP запрашивает время компиляции.
Независимый от архитектуры способ обнаружения 32-битных и 64-битных сборок в C и C++ выглядит так:
// C
#include <stdint.h>
// C++
#include <cstdint>
#if INTPTR_MAX == INT64_MAX
// 64-bit
#elif INTPTR_MAX == INT32_MAX
// 32-bit
#else
#error Unknown pointer size or missing size macros!
#endif
И вы даже можете добавить что-то для 16-битных и 8-битных процессоров! Определенный голос за это.
Аналогичный вопрос задан здесь на SO ... с действительно отличным ответом.