В Visual Studio 14
stdint.h
В заголовке есть определения для целочисленных типов фиксированной ширины, но если вы действительно посмотрите на определения, они просто делегируют обратно примитивам. Определения следующие:
typedef signed char int8_t;
typedef short int16_t;
typedef int int32_t;
typedef long long int64_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
Так есть ли основания использовать stdint.h
если все, что он делает, это просто откат к примитивам? Я также знаю, что Visual Studio не просто заменяет эти определения во время компиляции, потому что если вы попытаетесь распечатать int8_t
на консоли вы получите символ Unicode вместо числа, потому что это на самом деле просто signed char
,
Потому что люди указывают на то, что нет ничего другого, что они могли бы логически определить, так как я думаю, что мой вопрос нуждается в пересмотре.
Почему заголовок, который в спецификации C ++ гласит, что он будет иметь целые числа фиксированной длины 8, 16, 32 и 64 бита, определяет эти целые числа как типы, которые по определению могут быть любого размера, который компилятор хочет (поместить в как сказал кто-то другой в другом вопросе The compiler can decide that an int will a 71 bit number stored in a 128 bit memory space where the additional 57 bits are used to store the programmers girlfriends birthday.
)?
Как из первоначальных, так и из повторных вопросов я понимаю, что существует неправильное представление о целых числах с гарантированной шириной (и я говорю гарантированно, потому что не все типы в stdint.h
имеют фиксированную ширину) и реальные проблемы, которые они решают.
C / C ++ определяют примитивы, такие как int
, long int
, long long int
и т.д. Для простоты давайте сосредоточимся на наиболее распространенных из всех, то есть int
, Что определяет стандарт С, так это то, что int
должен иметь ширину не менее 16 бит. Хотя компиляторы на всех широко используемых платформах x86 на самом деле предоставят вам 32-битное целое число, когда вы определите int
, Это происходит потому, что процессоры x86 могут напрямую извлекать 32-разрядное поле (размер слова 32-разрядного процессора x86) из памяти, предоставлять его в виде ALU для 32-разрядной арифметики и сохранять его обратно в память без необходимости выполнять какие-либо действия. сдвиги, отступы и т. д., и это довольно быстро. Но это не так для каждой комбинации компилятор / архитектура. Если вы работаете на встроенном устройстве, например, с очень маленьким процессором MIPS, вы, вероятно, получите 16-битное целое число от компилятора при определении int
, Таким образом, ширина примитивов определяется компилятором в зависимости исключительно от аппаратных возможностей целевой платформы по отношению к минимальной ширине, определенной стандартом. И да, на странной архитектуре, например, с 25-битный ALU, вам, вероятно, дадут 25-битный int
,
Для того, чтобы фрагмент кода C / C ++ был переносимым среди множества различных комбинаций компилятор / аппаратное обеспечение, stdint.h
предоставляет typedefs, которые гарантируют вам определенную ширину (или минимальную ширину). Так, например, когда вы хотите использовать 16-разрядное целое число со знаком (например, для экономии памяти или счетчиков модов), вам не нужно беспокоиться о том, следует ли использовать int
или же short
, просто используя int16_t
, Разработчики компилятора предоставят вам правильно сконструированные stdint.h
это определит запрошенное целое число фиксированного размера в фактическом примитиве, который его реализует. Это означает, что на x86 int16_t
вероятно будет определяться как short
в то время как на небольшом встроенном устройстве вы можете получить int
со всеми этими отображениями, поддерживаемыми разработчиками компилятора.
Различные платформы определяют примитивы по-разному. На одной платформе int
может быть 16-битным, в то время как для другого 32-битным. Если вы строго зависите от переменной, имеющей определенную ширину, вы должны использовать типы в stdint.h
, который всегда будет typedef
Правильно, чтобы их соответствующие примитивы на текущей платформе.
Так есть ли причина использовать stdint.h, если все, что он делает, это просто откат к примитивам?
Что еще это будет делать?
Все типы, определенные в заголовках, можно отследить до встроенных типов.
Этот заголовок просто дает вам удобные, стандартные, гарантированно согласованные псевдонимы.
В ответ на вновь сформулированный вопрос, это не компилятор, делающий выбор, чтобы сохранить день рождения в старших 57 битах. Это был разработчик. Компилятор не может использовать любую битовую глубину для целочисленного типа. Он будет использовать любую битовую глубину, указанную разработчиками компилятора, и разработчики выберут эти битовые глубины в соответствии с требования стандарта C ++. Как только компилятор настроен и скомпилирован, глубина в битах не изменится1. Эти 71 бит будут гарантированы, пока вы не измените компиляторы или версии компиляторов.
Написание хорошего кода достаточно сложно без того, чтобы компилятор бросал в вас переменные. Рассмотрим, что может случиться с переменной глубиной в битах. Входные данные, которые были очень хорошими во вторник во время сборки, переполняют и приводят к падению лайнера, потому что в среду компилятор выполнил некоторые вычисления и решил, что никогда не увидит ничего больше 17 бит.
1 Я полагаю, вы могли бы создать компилятор, который загружал бы целочисленные размеры из файла конфигурации во время выполнения, но я подозреваю, что это сделало бы написание оптимизатора ужасно сложным.