Как определить, компилирую ли я 64-битную архитектуру на C++?

В функции C++ мне нужно, чтобы компилятор выбрал другой блок, если он компилируется для 64-битной архитектуры.

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

Аналогичный вопрос задан здесь на SO ... с действительно отличным ответом.

paxos1977 29.10.2008 05:41
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
25
1
18 740
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Это работает для MSVC++ и g++:

#if defined(_M_X64) || defined(__amd64__)
  // code...
#endif

… Но не работает, если вы ориентируетесь на ARM64 или любую другую архитектуру.

DarkDust 22.09.2015 15:19

Раймонд покрывает это.

Это специфично для Visual C++.

rdb 22.11.2014 16:20

@rdb Первая часть, потом идет Если вы не хотите привязывать себя к конкретному компилятору, вам придется ...

GSerg 22.11.2014 18:59

Эта статья вводит в заблуждение и неверна! Попробуйте ifdef _X86_ в Visual Studio, ничего не добавляя.

Pavel P 05.03.2018 01:00

@Pavel При всем уважении, вам нужно многому научиться, прежде чем вы сможете сказать, что статья Раймонда Чена вводит в заблуждение и неверна. Что касается _X86_, он прямо говорит: // assumes you use makefile.def [from the Windows DDK mentioned in the previous sentence], то есть где это определено.

GSerg 05.03.2018 09:48

@GSerg спасибо за указание, я только что прочитал его статью. Он совершенно прав, ваш ответ неверен и вводит в заблуждение.

Pavel P 05.03.2018 09:53

Ссылка теперь не работает. Статья перенесена на devblogs.microsoft.com/oldnewthing/20060906-07/?p=29843

Max Barraclough 10.03.2021 15:13

Если вы компилируете для платформы Windows, вам следует использовать:

#ifdef _WIN64

Компилятор MSVC определяет это как для платформ x64, так и для платформ ia64 (вы же не хотите сокращать этот рынок, не так ли?). Я не уверен, что gcc делает то же самое, но должен, если нет.

Альтернативой является

#ifdef WIN64

в котором есть небольшая разница. WIN64 (без подчеркивания в начале) определяется SDK (или конфигурацией сборки). Поскольку это определяется конфигурацией SDK / build, она также должна работать с gcc.

#ifdef _LP64

Работает на обеих платформах

Но разве не Windows ILP64?

Craig Ringer 25.06.2014 17:41

@CraigRinger Windows - это LLP64. По какой-то странной причине макрос все равно определен, что меня расстраивает.

S.S. Anne 01.04.2019 03:17
Ответ принят как подходящий

Почему вы выбираете один блок другому? Если ваше решение основано на размере указателя, используйте sizeof(void*) == 8. Если ваше решение основано на размере целого числа, используйте sizeof(int) == 8.

Я считаю, что название самой архитектуры редко имеет какое-либо значение. Вы проверяете только то, что вам нужно проверить, для целей того, что вы собираетесь делать. Ваш вопрос не очень четко описывает, какова ваша цель проверки. То, что вы спрашиваете, похоже на попытку определить, установлен ли DirectX, путем запроса версии Windows. В вашем распоряжении более портативные и универсальные инструменты.

sizeof (int) - не лучший пример. Это зависит от компилятора. Я пробовал 64-битный Linux с g ++, и он был длиной 4 байта. Лучше использовать sizeof (void *), чтобы определить архитектор. Но я не уверен, что это одинаково на всех машинах.

klew 15.02.2009 20:24

@klew, я думаю, вы упустили точку зрения flodin: «Вы проверяете только то, что вам нужно проверить, для целей того, что вы собираетесь делать».

foraidt 30.03.2009 18:13

Но ни один из них не работает в препроцессоре, например. #if sizeof(int)==4 - поскольку препроцессор не разрешает sizeof в выражениях #if.

greggo 15.10.2014 20:28

@greggo Вы можете использовать, например, INT_MAX вместо этого. См., Например, <cstdint>.

flodin 15.10.2014 23:35

@klew Да, int всегда будет 32-битным независимо от архитектуры для обратной совместимости. int64_t (uint64_t для беззнакового) требуется для 64-битных чисел.

FluorescentGreen5 25.09.2016 09:39

Цель проверки явно выходит за рамки вопроса. Неважно. Как бы «редко» ни была такая необходимость, по вашей оценке, случаи, когда она нужна, действительно существуют.

Swiss Frank 02.02.2020 16:01

Если вы используете 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 запрашивает время компиляции.

tibur 12.09.2014 17:09

Независимый от архитектуры способ обнаружения 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-битных процессоров! Определенный голос за это.

S.S. Anne 01.04.2019 03:15

Другие вопросы по теме