2009-08-17 2 views
5

Как гласит название, существует ли какой-либо элегантный и безопасный способ определить, является ли архитектура 32-битной или 64-битной. Благодаря элегантности вы можете думать о точном, правильном, коротким, чистым и умным образом. Безопасно, подумайте о безопасности с точки зрения стандартного, C89/C99 и независимости операционной системы.Элегантный и безопасный способ определить, является ли архитектура 32-битной или 64-битной.

+13

В C, вопрос неоднозначен: вы хотите, чтобы узнать код программы, является ли 64-битным кодом, или поддерживает ли процессор 64-битный код (т.е. в виде компиляции или его тест времени выполнения)? –

+6

Вы имеете в виду во время компиляции или во время выполнения? Любая конкретная ОС? –

+1

На вопрос нельзя ответить без предварительного определения того, что вы подразумеваете под 32-разрядной или 64-разрядной архитектурой. Нет общепринятого определения. –

ответ

3

Размер указателей на самом деле не очень хорошая вещь для проверки - в стандарте 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 Гб.)

2

Наиболее распространенным способом является проверка sizeof(void*) и sizeof(int) (обратите внимание, что они необязательно должны быть одинаковыми).

Другая возможность для процессоров x86/x64 - проверить флаг «lm». Если он присутствует, CPU понимает набор инструкций AMD64.

+0

Что вы предлагаете - это найти оба размера, а затем определить архитектуру. Другое предложение, чтобы проверить флаг «lm», звучит так, что для него требуется код ассемблера в C. Справа? – mtasic85

+1

Я только видел тест для конкретных инструкций в коде (и он был ассемблером, да). Однако многие ОС демонстрируют флаг CPU в пользовательской области. Linux, например, дает вам эту информацию в/proc/cpuinfo. Но это приведет к коду, зависящему от ОС. – ypnos

+1

Что делать, если у вас 32-битная версия компилятора, работающая на 64-разрядной машине, наверняка это не сработает? – Matt

9

короткий ответ: нет

длинного ответа: это зависит от слишком многих ОС комбинаций/компилятора. Например, во время выполнения в linux вы можете запросить файловую систему proc, тогда как в окнах вы можете запросить регистр.

Вы можете доказать, что компилятор, которые используются для компиляции имеет 32/64 бит целевой используя что-то вроде:

bool is_32bit() { 
    return sizeof(int *) == 4; 
} 

bool is_64bit() { 
    return sizeof(int *) == 8; 
} 

это может работает под несколько предположений (например, он работает во время выполнения). Вы можете найти компиляцию #define для своей платформы, но это хорошо известный беспорядок.

+0

Если вы включите оптимизацию, она не будет оцениваться во время выполнения, то ненужный код 32/64 бит будет удален. Кроме того, * bool * не входит в какой-либо стандарт C. – jbcreix

+5

«Кроме того, bool не входит ни в один стандарт C». - false, он находится в стандарте C99 в - http://en.wikipedia.org/wiki/Stdbool.h –

+0

oops. точка взята, тем не менее, это не C89, который указан в вопросе, вероятно, из-за таких странных вещей в c99. – jbcreix

7

Если вы используете GCC (как указано в тегах), вы можете проверить, как тест компиляции

#if __SIZEOF_POINTER__ == 8 

, чтобы выяснить, является ли это 64-разрядная система. Убедитесь, что используемая вами версия GCC определяет __SIZEOF_POINTER__, прежде чем использовать ее.

+1

Это решает проблему во время компиляции для GCC, и пока все в порядке. – mtasic85

+1

+0 Ответ dfa переносится (как только вы удалите его посторонний тип bool), и сделает код более чистого. Функция всегда возвращает true или false, и компилятор удалит ненужный код. – jbcreix

2

Безопасная и переносная техника, к сожалению, невозможна (поскольку безопасный и портативный позволяет вам только правила в стандарте 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 *) будет достаточным и переносимым через компиляторы.

+1

Вы можете умножить sizeof (void *) на CHAR_BIT, чтобы найти его размер в битах (хотя, но стандарт не гарантирует, что все биты в представлении являются битами ценности - фактически, в текущих реализациях x86_64 обычно есть только где-то в регионе из 48 битов значения в виртуальном адресе). – caf

1

32-бит на код банка или 32-бит в банке данных. :-) Процессоры 8086 имели 16-разрядные данные с 20-разрядной кодовой памятью. Кроме того, современные машины Havard делают странные вещи с разделением кода/данных ...

Вы можете проверить инструкцию cpuid для процессоров x86. Другие семейства процессоров могут не иметь такой инструкции ... YMMV.

1
int iedx; 

__asm 
{ 

mov eax, 0x80000001; 
cpuid; 
mov, iedx,edx; 
} 

    if (iedx & (1 << 29)) 
     { 
     return 1; 
     } 
    return 0; 
+0

Архитектура компьютера в большинстве случаев относится не к x86 и x86_64, а к общей архитектуре. Этот код не является стандартным и не переносимым. – osgx

 Смежные вопросы

  • Нет связанных вопросов^_^