Вопрос о том, как условная компиляция в системных заголовочных файлах (например, <sys/types.h>
) управляет процессом компиляции, путала меня в течение длительного времени. Например, здесь один общий фрагмент кода typedef в <sys/types.h>
:
# if __WORDSIZE == 64
typedef long int int64_t;
# elif __GLIBC_HAVE_LONG_LONG
__extension__ typedef long long int int64_t;
# endif
# endif
Тем не менее, если __WORDSIZE == 64
, то мы определяем тип int64_t
как один псевдоним long int
, но мне интересно, где я могу найти определение __WORDSIZE
.
__WORDSIZE
ли макрос __WORDSIZE
статическим в определенном файле? Если да, то как этот файл создается?В конце концов, как я могу написать один заголовочный файл, который может достичь следующего намерения:
#if the machine is 64-bit
typedef unsigned long int KEY_TYPE
#elif the machine is 32-bit
typedef unsigned long long int KEY_TYPE
#endif
Это зависит от компилятора и системы. Он (__WORDSIZE
) может быть определен компилятором как встроенный макрос (который может меняться в зависимости от параметров компилятора), или он может быть в системном заголовке. Чтение системных заголовков - это тяжелая работа в лучшем случае; в общем, вы не должны пытаться вторгаться в то, что в них.
Обратите внимание, что __WORDSIZE
находится в пространстве имен, зарезервированном для реализации. Реализация может делать то, что ему нравится, поскольку она работает правильно. Если вы __WORDSIZE
свой код к __WORDSIZE
, вы можете столкнуться с проблемами при изменении версий компилятора, брендов компилятора, версий операционной системы, брендов операционной системы.
Что касается того, как компилятор определяет, в какой системе он находится: это проблема компилятора. Он создан для генерации кода для конкретной системы (обычно это хост-система, если она не является кросс-компилятором). Компилятор настроен так, чтобы знать, как правильно скомпилировать код; как создать 32-битный объектный код или программы, а также как создать 64-битный объектный код или программы. Это было бы не очень полезно в качестве компилятора, если бы он не знал, как правильно создать код, не так ли?
Вы можете достичь своей цели:
// #include <stdint.h> // C header
#include <cstdint> // C++ analogue of <stdint.h>
typedef uint64_t KEY_TYPE;
Никакой условной компиляции в вашем коде - это лучший способ написать код.
(Предостережение: Технически, uint64_t
является необязательным типом. Однако похоже, что у вас будут проблемы, независимо от того, недоступен ли он.)
Чтобы обнаружить встроенные функции gcc (перед компиляцией любых файлов), попробуйте использовать:
gcc -std = С++ 11 -E -P -v -dD temp.cpp
(temp.cpp просто должен быть пустым файлом)
Измените -std = С++ 11 на требуемый стандарт.
Некоторые из этих встроенных определений будут использоваться для управления компиляцией файлов заголовков системы.
Некоторые из встроенных определений используются только для внутреннего (до gcc). Вам нужно будет обратиться к документации gcc, чтобы узнать, какие из встроенных функций вы можете использовать в своей версии gcc.
gcc -m64
для генерации 64-битного объектного кода иgcc -m32
для генерации 32-битного кода, каждый раз запуская один и тот же компилятор. Если я попытаюсь использовать компилятор для Mac OS X на компьютере с Linux, он не запустится, и наоборот, так что да, компилятор знает, на каком типе машины он установлен. Компилятор, построенный как 64-разрядный двоичный файл, также не будет работать на машине, которая поддерживает только 32-разрядные двоичные файлы. Таким образом, вы (человек, запускающий компилятор) управляете параметрами компилятора, хотя компилятор будет иметь значения по умолчанию, которые он использует, если вы не переопределите их.