Что означает стандарт C ++ для размера int, длинного типа?

Я ищу подробную информацию о размере базовых типов C ++. Я знаю, что это зависит от архитектуры (16 бит, 32 бит, 64 бит) и компилятора.

Но существуют ли стандарты для C ++?

Я использую Visual Studio 2008 в 32-битной архитектуре. Вот что я получаю:

char : 1 byte short : 2 bytes int : 4 bytes long : 4 bytes float : 4 bytes double: 8 bytes 

Я пытался найти, без особого успеха, надежную информацию о размерах char , short , int , long , double , float (и других типов, о которых я не думал) в разных архитектурах и компиляторах.

В стандарте C ++ не указывается размер интегральных типов в байтах, но он указывает минимальные диапазоны, которые они должны удержать. Вы можете вывести минимальный размер в битах из требуемого диапазона. Вы можете вывести минимальный размер в байтах из этого и значение макроса CHAR_BIT , определяющего количество бит в байте (на всех, кроме самых неясных платформах, это 8, и оно не может быть меньше 8).

Еще одно ограничение для char состоит в том, что его размер всегда равен 1 байту или бит CHAR_BIT (отсюда и название).

Минимальные диапазоны, требуемые стандартом (стр. 22):

и диапазоны данных в MSDN :

  1. signed char : от -127 до 127 (обратите внимание, что не от -128 до 127, это соответствует платформам с 1-го уровня и знаками и знаками)
  2. unsigned char : от 0 до 255
  3. «plain» char : тот же диапазон, что и signed char или unsigned char , определенный реализацией
  4. signed short : -32767 до 32767
  5. unsigned short : от 0 до 65535
  6. signed int : от -32767 до 32767
  7. unsigned int : от 0 до 65535
  8. signed long : -2147483647 по 2147483647
  9. unsigned long : от 0 до 4294967295
  10. signed long long : -9223372036854775807 по 9223372036854775807
  11. unsigned long long : от 0 до 18446744073709551615

Реализация C ++ (или C) может определять размер типа в байтах sizeof(type) для любого значения, если

  1. выражение sizeof(type) * CHAR_BIT вычисляет количество бит, достаточно высокое, чтобы содержать требуемые диапазоны, и
  2. упорядочение типа остается в силе (например, sizeof(int) <= sizeof(long) ).

Фактические диапазоны конкретных реализаций можно найти в заголовке в C или в C ++ (или даже лучше, templated std::numeric_limits в заголовке ).

Например, так вы найдете максимальный диапазон для int :

C:

 #include  const int min_int = INT_MIN; const int max_int = INT_MAX; 

C ++ :

 #include  const int min_int = std::numeric_limits::min(); const int max_int = std::numeric_limits::max(); 

Для 32-битных систем стандартом de facto является ILP32, то есть int , long и указатель – все 32-битные величины.

Для 64-битных систем основным стандартом Unix de facto является LP64 – long а указатель – 64-разрядный (но int 32-бит). Стандарт Windows 64-бит – LLP64 – long long а указатель – 64-разрядный (но long и int оба 32-разрядные).

В свое время некоторые Unix-системы использовали организацию ILP64.

Ни один из этих стандартов де-факто не законодательно закреплен стандартом C (ISO / IEC 9899: 1999), но все они разрешены им.

И, по определению, sizeof(char) равен 1 , несмотря на тест в скрипте Perl configure.

Обратите внимание, что были машины (Crays), где CHAR_BIT был намного больше 8. Это означало, что IIRC, что sizeof(int) также был 1, потому что оба char и int были 32-битными.

На практике такой вещи нет. Часто вы можете ожидать, что std::size_t будет представлять собственный целочисленный размер без знака в текущей архитектуре. т.е. 16-битный, 32-разрядный или 64-разрядный, но это не всегда так, как указано в комментариях к этому ответу.

Что касается всех других встроенных типов, это действительно зависит от компилятора. Вот два отрывка, взятых из текущего рабочего проекта последнего стандарта C ++:

Существует пять стандартных знаковых целочисленных типов: подписанный char, short int, int, long int и long long int. В этом списке каждый тип содержит как минимум столько же памяти, сколько и предшествующие ему в списке.

Для каждого стандартного знакового целочисленного типа существует соответствующий (но другой) стандартный беззнаковый целочисленный тип: unsigned char, unsigned short int, unsigned int, unsigned long int и unsigned long long int, каждый из которых занимает такое же количество хранения и имеет те же требования к выравниванию.

Если вы хотите, вы можете статически (время компиляции) утверждать размер этих основных типов. Это заставит людей подумать о портировании вашего кода, если меняются значения sizeof.

Есть стандарт.

Стандарт C90 требует, чтобы

 sizeof(short) <= sizeof(int) <= sizeof(long) 

Стандарт C99 требует, чтобы

 sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long) 

Вот спецификации C99 . Page 22 детализируют размеры разных интегральных типов.

Ниже приведены размеры (бит) типа int для платформ Windows:

 Type C99 Minimum Windows 32bit char 8 8 short 16 16 int 16 32 long 32 32 long long 64 64 

Если вы заинтересованы в переносимости или хотите, чтобы имя типа отображало размер, вы можете посмотреть заголовок , где доступны следующие macros:

 int8_t int16_t int32_t int64_t 

int8_t гарантированно будет 8 бит, а int16_t гарантированно будет 16 бит и т. д.

Если вам нужны фиксированные типы размеров, используйте такие типы, как uint32_t (беззнаковое целое число 32 бит), определенное в stdint.h . Они указаны на C99 .

Обновлено: C ++ 11 официально включил типы из TR1 в стандарт:

  • long long int
  • unsigned long long int

И «размерные» типы из

  • int8_t
  • int16_t
  • int32_t
  • int64_t
  • (и неподписанных коллег).

Плюс вы получаете:

  • int_least8_t
  • int_least16_t
  • int_least32_t
  • int_least64_t
  • Плюс неподписанные копии.

Эти типы представляют наименьшие целочисленные типы с по меньшей мере указанным количеством бит. Точно так же существуют «самые быстрые» целые типы с по меньшей мере указанным количеством бит:

  • int_fast8_t
  • int_fast16_t
  • int_fast32_t
  • int_fast64_t
  • Плюс неподписанные версии.

То, что «быстро» означает, во всяком случае, зависит от реализации. Это не должно быть самым быстрым для всех целей.

Стандарт C ++ говорит так:

3.9.1, §2:

Существует пять подписанных целочисленных типов: «signed char», «short int», «int», «long int» и «long long int». В этом списке каждый тип содержит как минимум столько же памяти, сколько и предшествующие ему в списке. Обычные размеры имеют естественный размер, предложенный архитектурой среды исполнения (44); другие подписанные целочисленные типы предоставляются для удовлетворения особых потребностей.

(44), который достаточно велик, чтобы содержать любое значение в диапазоне INT_MIN и INT_MAX, как определено в заголовке .

Вывод: это зависит от того, с какой архитектурой вы работаете. Любое другое предположение неверно.

Нет, нет стандарта для типовых размеров. Стандарт требует только того, чтобы:

 sizeof(short int) <= sizeof(int) <= sizeof(long int) 

Лучшее, что вы можете сделать, если хотите переменные фиксированных размеров - использовать macros следующим образом:

 #ifdef SYSTEM_X #define WORD int #else #define WORD long int #endif 

Затем вы можете использовать WORD для определения ваших переменных. Не то, чтобы мне это нравилось, но это самый портативный способ.

Нам разрешено определять синоним типа, чтобы мы могли создать наш собственный «стандарт».

На машине, в которой sizeof (int) == 4, мы можем определить:

 typedef int int32; int32 i; int32 j; ... 

Поэтому, когда мы передаем код на другую машину, где на самом деле размер long int равен 4, мы можем просто переопределить одно вхождение int.

 typedef long int int32; int32 i; int32 j; ... 

Для чисел с плавающей запятой существует стандарт (IEEE754) : поплавки – 32 бит, а удваивается – 64. Это аппаратный стандарт, а не стандарт C ++, поэтому компиляторы теоретически могут определять float и double до некоторого другого размера, но на практике я ‘ Никогда не видел архитектуры, которая использовала что-то другое.

Существует стандарт и указан в различных документах стандартов (ISO, ANSI и еще что-то).

В Википедии есть отличная страница, объясняющая различные типы и максимальные значения, которые они могут хранить: Integer in Computer Science.

Однако даже со стандартным компилятором C ++ вы можете легко найти следующий fragment кода:

 #include  #include  int main() { // Change the template parameter to the various different types. std::cout << std::numeric_limits::max() << std::endl; } 

Документацию для std :: numeric_limits можно найти в Roguewave . Он включает в себя множество других команд, которые вы можете вызвать, чтобы узнать различные пределы. Это можно использовать с любым произвольным типом, который передает размер, например std :: streamsize.

Ответ Джона содержит лучшее описание, которое гарантировано. Независимо от того, на какой платформе вы находитесь, есть еще одна хорошая страница, которая более подробно описывает, сколько битов каждого типа ДОЛЖНО содержать: типы int , которые определены в стандарте.

Надеюсь, это поможет!

1) Таблица N1 в статье « Забытые проблемы разработки 64-битных программ »

2) « Модель данных »

Вы можете использовать:

 cout << "size of datatype = " << sizeof(datatype) << endl; 

datatype = int , long int и т. д. Вы сможете увидеть размер для любого типа данных, который вы вводите.

Когда дело доходит до встроенных типов для разных архитектур и разных компиляторов, просто запустите следующий код в своей архитектуре с вашим компилятором, чтобы узнать, что он выводит. Ниже показан мой 64-битный выход 6,4 бит Ubuntu 13.04 (Raring Ringtail). Также обратите внимание на то, что было ответировано ниже, и почему вывод упорядочен как таковой:

«Существует пять стандартных стандартных целочисленных типов: signed char, short int, int, long int и long long int. В этом списке каждый тип содержит как минимум столько же памяти, сколько и предшествующие ему в списке».

 #include  int main ( int argc, char * argv[] ) { std::cout<< "size of char: " << sizeof (char) << std::endl; std::cout<< "size of short: " << sizeof (short) << std::endl; std::cout<< "size of int: " << sizeof (int) << std::endl; std::cout<< "size of long: " << sizeof (long) << std::endl; std::cout<< "size of long long: " << sizeof (long long) << std::endl; std::cout<< "size of float: " << sizeof (float) << std::endl; std::cout<< "size of double: " << sizeof (double) << std::endl; std::cout<< "size of pointer: " << sizeof (int *) << std::endl; } size of char: 1 size of short: 2 size of int: 4 size of long: 8 size of long long: 8 size of float: 4 size of double: 8 size of pointer: 8 

Как уже упоминалось, размер должен отражать текущую архитектуру. Вы можете взять пик вокруг в пределах. limits.h если вы хотите увидеть, как ваш текущий компилятор обрабатывает вещи.

Как уже говорили другие, «стандарты» оставляют большинство деталей «определенной» реализацией и указывают только, что тип «char» находится в «char_bis» шириной и что «char <= short <= int <= long < = long long "(float и double в значительной степени соответствуют стандарту IEEE с плавающей запятой, а long double обычно является таким же, как double, но может быть больше для более современных реализаций).

Часть причин не иметь очень конкретных и точных значений заключается в том, что такие языки, как C / C ++, были предназначены для переносимости на большое количество аппаратных платформ. Включая компьютерные системы, в которых размер слова «char» может быть 4-битным или 7 бит, или даже другое значение, отличное от компьютеров с 8 “/ 16- / 32- / 64-разрядными”, которым подвергается обычный пользователь домашнего компьютера. (Размер слова здесь означает, сколько битов шириной система обычно работает – Опять же, это не всегда 8 бит, как пользователи домашних компьютеров могут ожидать.)

Если вам действительно нужен объект (в смысле серии бит, представляющий целое значение) определенного количества бит, большинство компиляторов имеют некоторый способ указания этого; Но, как правило, он не переносится даже между компиляторами, производимыми компанией ame, но для разных платформ. Некоторые стандарты и методы (особенно limits.h и т. П.) Достаточно распространены, что большинство компиляторов будут иметь поддержку для определения типа наилучшего соответствия для определенного диапазона значений, но не для количества используемых битов. (То есть, если вы знаете, что вам нужно хранить значения от 0 до 127, вы можете определить, что ваш компилятор поддерживает 8-битный тип «int8», который будет достаточно большим, чтобы удерживать весь желаемый диапазон, но не что-то вроде тип “int7”, который был бы точным совпадением для 7 бит.)

Примечание. Многие исходные пакеты Un * x используют сценарий «./configure», который будет исследовать возможности компилятора / системы и выводить подходящий Makefile и config.h. Вы можете изучить некоторые из этих сценариев, чтобы узнать, как они работают и как они исследуют возможности компилятора / системы, и следовать их примеру.

Если вас интересует чистое решение на C ++, я использовал шаблоны и только стандартный код C ++ для определения типов во время компиляции на основе их размера бит. Это делает решение переносимым для всех компиляторов.

Идея очень проста: создайте список, содержащий типы char, int, short, long, long long (подписанные и неподписанные версии) и сканирование списка, а с помощью шаблона numeric_limits выберите тип с заданным размером.

Включая этот заголовок, вы получаете 8 типов stdtype :: int8, stdtype :: int16, stdtype :: int32, stdtype :: int64, stdtype :: uint8, stdtype :: uint16, stdtype :: uint32, stdtype :: uint64.

Если какой-либо тип не может быть представлен, он будет оцениваться как stdtype :: null_type, также объявленный в этом заголовке.

КОДЕКС НИЖЕ НЕ ПРЕДОСТАВЛЯЕТСЯ БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ПОЖАЛУЙСТА, ДВОЙНАЯ ПРОВЕРКА.
Я НОВЫЙ В МЕТАПРОГРАММИРОВАНИИ СЛИШКОМ, ЧУВСТВУЮТ, ЧТОБЫ ИЗМЕНИТЬ И ИСПРАВИТЬ ЭТОТ КОД.
Протестировано с DevC ++ (поэтому версия gcc около 3.5)

 #include  namespace stdtype { using namespace std; /* * THIS IS THE CLASS USED TO SEMANTICALLY SPECIFY A NULL TYPE. * YOU CAN USE WHATEVER YOU WANT AND EVEN DRIVE A COMPILE ERROR IF IT IS * DECLARED/USED. * * PLEASE NOTE that C++ std define sizeof of an empty class to be 1. */ class null_type{}; /* * Template for creating lists of types * * T is type to hold * S is the next type_list type * * Example: * Creating a list with type int and char: * typedef type_list > test; * test::value //int * test::next::value //char */ template  struct type_list { typedef T value; typedef S next; }; /* * Declaration of template struct for selecting a type from the list */ template  struct select_type; /* * Find a type with specified "b" bit in list "list" * * */ template  struct find_type { private: //Handy name for the type at the head of the list typedef typename list::value cur_type; //Number of bits of the type at the head //CHANGE THIS (compile time) exp TO USE ANOTHER TYPE LEN COMPUTING enum {cur_type_bits = numeric_limits::digits}; public: //Select the type at the head if b == cur_type_bits else //select_type call find_type with list::next typedef typename select_type::type type; }; /* * This is the specialization for empty list, return the null_type * OVVERRIDE this struct to ADD CUSTOM BEHAVIOR for the TYPE NOT FOUND case * (ie search for type with 17 bits on common archs) */ template  struct find_type { typedef null_type type; }; /* * Primary template for selecting the type at the head of the list if * it matches the requested bits (b == ctl) * * If b == ctl the partial specified templated is evaluated so here we have * b != ctl. We call find_type on the next element of the list */ template  struct select_type { typedef typename find_type::type type; }; /* * This partial specified templated is used to select top type of a list * it is called by find_type with the list of value (consumed at each call) * the bits requested (b) and the current type (top type) length in bits * * We specialice the b == ctl case */ template  struct select_type { typedef typename list::value type; }; /* * These are the types list, to avoid possible ambiguity (some weird archs) * we kept signed and unsigned separated */ #define UNSIGNED_TYPES type_list > > > > #define SIGNED_TYPES type_list > > > > /* * These are acutally typedef used in programs. * * Nomenclature is [u]intN where u if present means unsigned, N is the * number of bits in the integer * * find_type is used simply by giving first a type_list then the number of * bits to search for. * * NB. Each type in the type list must had specified the template * numeric_limits as it is used to compute the type len in (binary) digit. */ typedef find_type::type uint8; typedef find_type::type uint16; typedef find_type::type uint32; typedef find_type::type uint64; typedef find_type::type int8; typedef find_type::type int16; typedef find_type::type int32; typedef find_type::type int64; } 
 unsigned char bits = sizeof(X) << 3; 

где X - char , int , long т. д., даст вам размер X в битах.

От Alex B В стандарте C ++ не указывается размер интегральных типов в байтах, но он указывает минимальные диапазоны, которые они должны удержать. Вы можете вывести минимальный размер в битах из требуемого диапазона. Вы можете вывести минимальный размер в байтах из этого и значение макроса CHAR_BIT, определяющего количество бит в байте (на всех, кроме самых неясных платформах, это 8, и оно не может быть меньше 8).

Еще одно ограничение для char состоит в том, что его размер всегда равен 1 байту или бит CHAR_BIT (отсюда и название).

Минимальные диапазоны, требуемые стандартом (стр. 22):

и диапазоны данных в MSDN:

подписанный char: от -127 до 127 (обратите внимание, не от -128 до 127, это относится к платформам с 1-м дополнением) unsigned char: от 0 до 255 «простой» символ: от -127 до 127 или от 0 до 255 (зависит от подписки по умолчанию) короткий: от -32767 до 32767 без знака short: от 0 до 65535 подписанный int: -32767 до 32767 unsigned int: от 0 до 65535 подписанный длинный: -2147483647 до 2147483647 беззнаковый длинный: от 0 до 4294967295 подписан длинный длинный: -9223372036854775807 до 9223372036854775807 unsigned long long: 0 до 18446744073709551615 Реализация C ++ (или C) может определять размер типа в байтах sizeof (type) для любого значения, если

выражение sizeof (type) * CHAR_BIT оценивает количество бит, достаточное для того, чтобы содержать требуемые диапазоны, и порядок типа все еще действителен (например, sizeof (int) <= sizeof (long)). Фактические диапазоны конкретных реализаций можно найти в заголовке на C или в C ++ (или даже лучше, в шаблоне std :: numeric_limits в заголовке).

Например, так вы найдете максимальный диапазон для int:

C:

 #include  const int min_int = INT_MIN; const int max_int = INT_MAX; 

C ++:

 #include  const int min_int = std::numeric_limits::min(); const int max_int = std::numeric_limits::max(); 

Это верно, однако, вы также были правы в том, что: char: 1 байт короткий: 2 байта int: 4 байта в длину: 4 байта float: 4 байта double: 8 байт

Поскольку 32-разрядные архитектуры по-прежнему являются стандартными и наиболее часто используемыми, и они сохранили эти стандартные размеры с 32-разрядных дней, когда память была менее доступной, а для обратной совместимости и стандартизации она осталась прежней. Даже 64-битные системы имеют тенденцию использовать их и имеют расширения / модификации. Пожалуйста, обратитесь к этому для получения дополнительной информации:

http://en.cppreference.com/w/cpp/language/types

Я замечаю, что все остальные ответы здесь сосредоточены почти исключительно на интегральных типах, в то время как вопросник также задал вопрос о плавающих точках.

Я не думаю, что это требует стандарт C ++, но компиляторы для наиболее распространенных платформ в наши дни обычно следуют стандарту IEEE754 для своих чисел с плавающей запятой. Этот стандарт указывает четыре типа двоичной с плавающей запятой (а также некоторые форматы BCD, которых я никогда не видел в компиляторах на C ++):

  • Половина точности (бинарный 16) – 11-бит значащий, диапазон экспоненциальных значений от -14 до 15
  • Single precision (binary32) – 24-битная значимость, диапазон экспоненциального диапазона от -126 до 127
  • Двойная точность (binary64) – 53-битная значимость, диапазон экспоненциального диапазона от -1022 до 1023
  • Четвёртая точность (binary128) – 113-разрядная значимость, диапазон экспоненциальных значений от -16382 до 16383

Как это происходит на C ++-типах? Обычно float использует одинарную точность; таким образом, sizeof(float) = 4 . Then double uses double precision (I believe that’s the source of the name double ), and long double may be either double or quadruple precision (it’s quadruple on my system, but on 32-bit systems it may be double). I don’t know of any compilers that offer half precision floating-points.

In summary, this is the usual:

  • sizeof(float) = 4
  • sizeof(double) = 8
  • sizeof(long double) = 8 or 16

As you mentioned – it largely depends upon the compiler and the platform. For this, check the ANSI standard, http://home.att.net/~jackklein/c/inttypes.html

Here is the one for the Microsoft compiler: Data Type Ranges .

You can use variables provided by libraries such as OpenGL , Qt , etc.

For example, Qt provides qint8 (guaranteed to be 8-bit on all platforms supported by Qt), qint16, qint32, qint64, quint8, quint16, quint32, quint64, etc.

On a 64-bit machine:

 int: 4 long: 8 long long: 8 void*: 8 size_t: 8 

There are four types of integers based on size:

  • short integer: 2 byte
  • long integer: 4 byte
  • long long integer: 8 byte
  • integer: depends upon the compiler (16 bit, 32 bit, or 64 bit)
  • Часто задаваемые вопросы: Почему dynamic_cast работает только в том случае, если class имеет не менее 1 виртуальный метод?
  • Что такое «Аргумент-зависимый поиск» (также известный как ADL или «Koenig Lookup»)?
  • Что такое идиома копирования и свопинга?
  • Каковы различия между переменной указателя и ссылочной переменной в C ++?
  • Уничтожение объектов в C ++
  • Что такое строгое правило сглаживания?
  • Что такое lambda-выражение в C ++ 11?
  • Каков любопытно повторяющийся шаблон шаблона (CRTP)?
  • Почему встроенные функции C ++ в заголовке?
  • Какие возможности C ++ Smart Pointer доступны?
  • Порядок оценки инициализации списка конструктора
  • Interesting Posts

    jqgrid изменить значение ячейки и оставаться в режиме редактирования

    Разрешение отклонено (публикация) при доступе SSH к экземпляру Amazon EC2

    Каков наилучший способ отменить распространение событий между вложенными вызовами ng-click?

    Сеть не может быть идентифицирована, какие требования должны соответствовать интерфейсу?

    Android Intent для отправки электронной почты с приложением

    Что происходит с тем, что происходит с памятью с памятью std :: deque?

    Отображение CSS: таблица min-height не работает

    Как включить поддержку языка ассемблера в Visual Studio 2013

    Как определить фактический размер на диске для папки в Windows 10

    Xcode 4 – создать выходной каталог

    перегрузка оператора друга << для шаблона classа

    Конструкторы против заводских методов

    Как resize шрифта и цвет текста?

    Источники питания для ноутбуков, текущие вопросы?

    Кастинг: (NewType) против объекта как NewType

    Давайте будем гением компьютера.