Как гласит название, существует ли какой-либо элегантный и безопасный способ определить, является ли архитектура 32-битной или 64-битной. Благодаря элегантности вы можете думать о точном, правильном, коротким, чистым и умным образом. Безопасно, подумайте о безопасности с точки зрения стандартного, C89/C99 и независимости операционной системы.Элегантный и безопасный способ определить, является ли архитектура 32-битной или 64-битной.
ответ
Размер указателей на самом деле не очень хорошая вещь для проверки - в стандарте C не так много, что вы можете сделать с результатом этого теста.
Мое предложение тест ((size_t)-1)
, наибольший размер объекта, который C понимает:
if ((size_t)-1 > 0xffffffffUL)
{
printf("> 32 bits\n");
}
else
{
printf("<= 32 bits\n");
}
Если это больше, чем 0xffffffffUL
, то вы можете в принципе иметь объекты размером более 2**32 - 1
байт, что кажется более значимым тест, чем туманный "32 бит против 64 бит".
(Например, если вы знаете, что максимальное значение size_t
только 2**32 - 1
, то нет никакого смысла пытаться mmap()
регион, больше, чем 1 или 2 Гб.)
Наиболее распространенным способом является проверка sizeof(void*)
и sizeof(int)
(обратите внимание, что они необязательно должны быть одинаковыми).
Другая возможность для процессоров x86/x64 - проверить флаг «lm». Если он присутствует, CPU понимает набор инструкций AMD64.
Что вы предлагаете - это найти оба размера, а затем определить архитектуру. Другое предложение, чтобы проверить флаг «lm», звучит так, что для него требуется код ассемблера в C. Справа? – mtasic85
Я только видел тест для конкретных инструкций в коде (и он был ассемблером, да). Однако многие ОС демонстрируют флаг CPU в пользовательской области. Linux, например, дает вам эту информацию в/proc/cpuinfo. Но это приведет к коду, зависящему от ОС. – ypnos
Что делать, если у вас 32-битная версия компилятора, работающая на 64-разрядной машине, наверняка это не сработает? – Matt
короткий ответ: нет
длинного ответа: это зависит от слишком многих ОС комбинаций/компилятора. Например, во время выполнения в linux вы можете запросить файловую систему proc, тогда как в окнах вы можете запросить регистр.
Вы можете доказать, что компилятор, которые используются для компиляции имеет 32/64 бит целевой используя что-то вроде:
bool is_32bit() {
return sizeof(int *) == 4;
}
bool is_64bit() {
return sizeof(int *) == 8;
}
это может работает под несколько предположений (например, он работает во время выполнения). Вы можете найти компиляцию #define
для своей платформы, но это хорошо известный беспорядок.
Если вы включите оптимизацию, она не будет оцениваться во время выполнения, то ненужный код 32/64 бит будет удален. Кроме того, * bool * не входит в какой-либо стандарт C. – jbcreix
«Кроме того, bool не входит ни в один стандарт C». - false, он находится в стандарте C99 в
oops. точка взята, тем не менее, это не C89, который указан в вопросе, вероятно, из-за таких странных вещей в c99. – jbcreix
Если вы используете GCC (как указано в тегах), вы можете проверить, как тест компиляции
#if __SIZEOF_POINTER__ == 8
, чтобы выяснить, является ли это 64-разрядная система. Убедитесь, что используемая вами версия GCC определяет __SIZEOF_POINTER__
, прежде чем использовать ее.
Безопасная и переносная техника, к сожалению, невозможна (поскольку безопасный и портативный позволяет вам только правила в стандарте C).
sizeof(int)
с некоторыми из наиболее распространенных компиляторов может дать вам 4 для 32-битной платформы и 8 для 64-битной платформы, но это не гарантируется. Все стандарты C говорят, что int должен быть «естественным» размером для вычислений на цели, и поэтому многие компиляторы оставили sizeof (int) как 4 даже в 64-битном мире на том основании, что он «достаточно» ».
sizeof(void*)
лучше, потому что указатель должен быть соответствующего размера для адресации всего адресного пространства. sizeof(void*)
, вероятно, даст вам 4 или 8, если необходимо. Технически, даже это не гарантируется, так как sizeof дает вам количество байтов, необходимых для хранения чего-либо, а байт не должен быть 8 бит. Байт - это технически наименьшая адресуемая единица памяти, которая, как правило, 8 бит на большинстве платформ, к которым привыкли люди. 8-битная адресация очень распространена, но я работаю с чипами, которые имеют 16-битный адресный и 16-разрядный размер слова (так sizeof(int)
равно 1). Итак, если размер вашего байта не 8 бит, то sizeof(void*)
может дать вам множество значений.
С другой стороны, если вы просто пытаетесь различать x86 и x64 (32-битные и 64-разрядные процессоры ПК), тогда sizeof (void *) будет достаточным и переносимым через компиляторы.
Вы можете умножить sizeof (void *) на CHAR_BIT, чтобы найти его размер в битах (хотя, но стандарт не гарантирует, что все биты в представлении являются битами ценности - фактически, в текущих реализациях x86_64 обычно есть только где-то в регионе из 48 битов значения в виртуальном адресе). – caf
32-бит на код банка или 32-бит в банке данных. :-) Процессоры 8086 имели 16-разрядные данные с 20-разрядной кодовой памятью. Кроме того, современные машины Havard делают странные вещи с разделением кода/данных ...
Вы можете проверить инструкцию cpuid
для процессоров x86. Другие семейства процессоров могут не иметь такой инструкции ... YMMV.
int iedx;
__asm
{
mov eax, 0x80000001;
cpuid;
mov, iedx,edx;
}
if (iedx & (1 << 29))
{
return 1;
}
return 0;
Архитектура компьютера в большинстве случаев относится не к x86 и x86_64, а к общей архитектуре. Этот код не является стандартным и не переносимым. – osgx
В C, вопрос неоднозначен: вы хотите, чтобы узнать код программы, является ли 64-битным кодом, или поддерживает ли процессор 64-битный код (т.е. в виде компиляции или его тест времени выполнения)? –
Вы имеете в виду во время компиляции или во время выполнения? Любая конкретная ОС? –
На вопрос нельзя ответить без предварительного определения того, что вы подразумеваете под 32-разрядной или 64-разрядной архитектурой. Нет общепринятого определения. –