#ifdef для 32-битной платформы
В приложении, которое я поддерживаю, мы столкнулись с проблемой ограничений файлового дескриптора, влияющих на stdlib. Эта проблема затрагивает только 32-разрядную версию стандартной библиотеки lib.
Я разработал исправление для своего кода и хотел бы его реализовать, но только при компиляции для 32-битного исполняемого файла. Какой символ препроцессора я могу указать #ifdef для определения того, компилируется ли код для 32 или 64-битной цели?
ИЗМЕНИТЬ
Извините, не упоминал, что код кросс-платформенный, linux, windows, solaris и несколько других unix-аксессуаров, в основном с использованием GCC для компиляции. Любые стандарты де-факто я могу использовать кросс-платформу?
РЕДАКТИРОВАТЬ 2
Я нашел некоторые определения "__ILP23" и "__LP64", которые, похоже, могут работать... обсуждение здесь объясняет предысторию на платформе unix. Кто-нибудь имел опыт использования этих определений? Это будет полезно?
Ответы
Ответ 1
Я не уверен, что есть универсальный #if def, который подходит. Стандарт С++ почти наверняка не определяет его. Конечно, есть платформы spcefic.
Например, Windows
#if _WIN64
// 64 bit build
#else
// 32 bit build
#endif
EDIT OP упомянул, что это кросс-компиляция между Windows и Non-Windows с использованием GCC и других компиляторов
Нет универсального макроса, который может использоваться для всех платформ и компиляторов. Немного препроцессорной магии, хотя может сделать трюк. Предполагая, что вы работаете только с чипами x86 и amd64, следующее должно сделать трюк. Его можно легко расширить для других платформ, но
#if _WIN64 || __amd64__
#define PORTABLE_64_BIT
#else
#define PORTABLE_32_BIT
#endif
Ответ 2
Я рекомендую закладок predef SourceForge. Там нет ни одного ответа, но это, безусловно, поможет вам начать работу.
EDIT: для кода GCC вы можете использовать __i386__
для проверки 32-разрядных чипов x86, и я предлагаю попробовать __X86_64__
или что-то похожее на проверку 64-разрядных чипов x86. (Примечание. Мне пришло в голову, что предыдущий ответ с участием __ia86__
на самом деле является отличным чипом, а не 64-разрядным чипом x86. Это просто показывает отсутствие аппаратного обеспечения. Для тех, кто больше разбирается в аппаратных средствах, чем я, consule на странице SourceForge на предопределенных макросах, которые я ссылаюсь на выше. Это гораздо более точный, чем я.) Есть и другие, которые будут работать, но эти два должны быть довольно универсальными среди версий GCC.
Ответ 3
Посмотрите на это:
макросы i386
Макросы AMD64
Ответ 4
Вы можете проверить известный тип для этого размера, например. sizeof (int *) == 4 для 32-битной платформы.
Поскольку sizeof известен в compiletime, я считаю,
if(sizeof(int*) == 4)
{
...
}
должен сделать трюк
Изменить: комментарии правы, вам нужно использовать регулярное, если #if не будет работать.
Если вы используете С++, вы можете создать шаблонный код и позволить компилятору выбрать специализацию для вас на основе вызова sizeof().
Если вы создадите для 32-битной платформы, компилятор только создаст код для 32-битной платформы.
Если вы создадите платформу размером 654 бит, компилятор только создаст код для 64-битной платформы.
Ответ 5
То, что я, вероятно, в конечном итоге сделаю, находится в Makefile, определите, находитесь ли вы на 32-битной платформе или 64-разрядной версии, используя uname. Затем добавьте в свои CFLAGS, -DX32 или -DX64. Это вы могли бы просто #ifdef X64.
Но это просто решение для unixy. Я не уверен, что делать с окнами.
Ответ 6
Как минимум 32-разрядная Solaris имеет ограничение в 256 указателей файлов, поскольку структура хранит дескриптор файла в неподписанном char поле. Это сохраняется для обратной совместимости с некоторыми почти невероятно старыми версиями SunOS. Другие платформы - я соблазн сказать большинство других платформ - не разделяю этого ограничения. С другой стороны, для обычной пользовательской программы относительно необычно, что многие файлы открываются одновременно; это чаще всего указывает на ошибку (не закрывая файлы, когда они заканчиваются с ними), чем нет. Сказав это, однако, это может быть проблемой для таких вещей, как серверы баз данных, которые должны иметь много файлов данных одновременно.
В одном комментарии говорится:
Это почти это. Мы не открываем большое количество файлов, но сервер обрабатывает большое количество подключений от клиентов. Ручки Socket и дескрипторы файлов, похоже, происходят из одного и того же места. Когда у нас много соединений, "fopen" терпит неудачу, потому что вызов системного уровня возвращается и fd > 255.
"Ручки Socket" - это дескрипторы файлов на уровне системных вызовов, поэтому они происходят из того же места, что и обычные дескрипторы файлов для файлов.
Если вам нужно обойти это, тогда вам нужно обернуть свой текущий код открытия сокета, чтобы, если он получает файловый дескриптор в диапазоне 0..255, он вызывает "dup2()
" для создания файлового дескриптора в диапазоне, который stdio не будет использовать, - и затем закройте исходный дескриптор файла. Единственная проблема с этим заключается в том, что вам нужно отслеживать, какие файловые дескрипторы доступны, потому что dup2
будет весело закрывать дескриптор целевого файла, если он в настоящий момент открыт.
Конечно, я предполагаю, что ваш код сокета считывает дескрипторы файлов, а не указатели файлов. В этом случае у вас большие проблемы - слишком много вещей хотят использовать одни и те же ресурсы, и они не могут использовать их одновременно.
Ответ 7
Зависит от вашей ОС и компилятора, это решения по внедрению.
Ответ 8
Я использую такую конструкцию для Windows:
#if defined(_WIN64)
//64-bit code
#elif defined(_M_IX86)
//32-bit code
#else
#error "Unknown platform"
#endif
Versus:
#if defined(_WIN64)
// 64 bit code
#else
// 32-bit code
#endif
В первом решении из-за #error компилятор сможет рассказать вам, где вам нужно добавить код для новой платформы. Это помогает поддерживать работоспособность, если вы когда-либо сталкиваетесь с платформой, которая не является ни 64-разрядной, ни 32-разрядной. Да, _M_IX86 не совсем синоним 32-битного, но я думаю, что только 32-битная платформа, которую большинство из нас поддерживает, на самом деле является x86. Так что практической меры достаточно.
В более позднем решении вам придется вручную определить, где вам нужен код для вашей новой платформы, используя grep или что-то в этом роде. Это утомительно и подвержено ошибкам.
Мне кажется, что следующая конструкция также будет приемлемой, хотя я не тестировал ее в производстве, и я действительно очень об этом думал.
#if defined(_WIN64)
//64-bit code
#elif defined(_WIN32)
//32-bit code
#else
#error "Unknown platform"
#endif
Ответ 9
Я считаю, что define - _WIN64
Ответ 10
Нет такого символа, который определен стандартом С++ - ваша конкретная платформа (которую вы не указали в своем вопросе) может предоставить один.
Ответ 11
Я бы протестировал это косвенно, через константу максимального значения указателя:
#include <stdint.h>
#if UINTPTR_MAX == 0xffFFffFF
// 32-bit platform
#elif UINTPTR_MAX == 0xffFFffFFffFFffFF
// 64-bit platform
#else
#error Unknown platform - does not look either like 32-bit or 64-bit
#endif
Таким образом, вы не полагаетесь ни на какое специфическое для платформы определение архитектуры, а на прямое следствие наличия конкретной архитектуры - размер указателя.