Какой стандарт C ++ указывает размер типа int, long?


697

Я ищу подробную информацию о размере основных типов 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(и другие типы я не думал) в различных архитектурах и компиляторов.


18
@thyrgle его не по выбору ... есть так много архитектур, чтобы поддерживать, что он должен быть гибким.
Краккос


4
Почему они не удаляют все расплывчатые типы и стандартизируют их для определенных типов длины в битах, например, int32_t, uint32_t, int64_t и т. Д.
developerbmw,

5
@thyrgle На самом деле довольно сложно стандартизировать что-то подобное. В отличие от Java, где эти вещи постоянны из-за того, как работает JVM, C / C ++ по существу должен придерживаться системы, на которой они работают, без каких-либо причудливых уровней абстракции (по крайней мере, не так много, как в Java). между. Если размер междунар является то , что важно , можно использовать int16_t, int32_tи int64_t(нужно iostreamвключают , что , если я правильно помню). Что приятно в этом, что int64_t не должно иметь проблем в 32-битной системе (хотя это повлияет на производительность).
rbaleksandar

5
@rbaleksandar Они на самом деле определены <cstdint>, а не <iostream>.
Джастин Тайм - Восстановить Монику

Ответы:


685

Стандарт C ++ не определяет размер целочисленных типов в байтах, но определяет минимальные диапазоны, которые они должны поддерживать. Вы можете вывести минимальный размер в битах из необходимого диапазона. Из этого вы можете определить минимальный размер в байтах и ​​значение CHAR_BITмакроса, который определяет количество бит в байте . На всех платформах, кроме самых непонятных, это 8, и оно не может быть меньше 8. Это потому, что он должен быть достаточно большим, чтобы вместить «восьмибитные кодовые единицы формы кодировки Unicode UTF-8».

Дополнительным ограничением charявляется то, что его размер всегда равен 1 байту или CHAR_BITбитам (отсюда и название). Это прямо указано в стандарте.

Стандарт C является нормативной ссылкой для стандарта C ++, поэтому, хотя он и не устанавливает эти требования в явном виде, для C ++ требуются минимальные диапазоны, требуемые стандартом C (стр. 22), которые такие же, как в диапазонах типов данных на MSDN :

  1. signed char: От -127 до 127 (примечание, не от -128 до 127; в нем предусмотрены платформы "1-дополнение" и "знак и величина")
  2. unsigned char: От 0 до 255
  3. «обычный» 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)).

Собрав все это вместе, мы гарантируем, что:

  • char, signed charИ unsigned char, по меньшей мере 8 бит
  • signed short, unsigned short, signed int, И unsigned int, по крайней мере , 16 бит
  • signed longи unsigned longне менее 32 бит
  • signed long longи unsigned long longне менее 64 бит

Мы не даем никаких гарантий относительно размера floatили doubleза исключением того, что doubleобеспечивает как минимум такую ​​же точность, какfloat .

Фактические специфичные для реализации диапазоны можно найти в <limits.h>заголовке в C или <climits>в C ++ (или даже лучше, в шаблоне std::numeric_limitsв <limits>заголовке).

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

C:

#include <limits.h>
const int min_int = INT_MIN;
const int max_int = INT_MAX;

C ++ :

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

49
Скорее стандарт C ++ использует слово « байт» для обозначения «1 char», а не для обычного значения.
Бен Фойгт

4
@Programmer Прочитайте ответ (примечание 1 в скобках) или фактическую формулировку стандарта (ссылка в ответе). Стандарт C вмещает в себя 1 комплементарную архитектуру, которая отличается от наиболее распространенного 2 комплементарного дополнения. Минимальные гарантированные диапазоны почти всегда будут отличаться от фактических диапазонов, которые обеспечивает реализация.
Алекс Б

9
@ Алекс Б, вы ничего не упомянули о двойном в своем ответе. Можете ли вы обновить свой ответ для переменных с плавающей запятой?
Cool_Coder

3
@Cool_Coder: с плавающей точкой это целый дополнительный чайник рыбы, легко удваивающий размер постов.
Дедупликатор

3
@Mooing Duck: «для всех версий C ++ требовалось 256 различных значений [для типов знаков со знаком]» Нет, это не было правдой, пока не было исправлено в более поздних спецификациях C ++. Старые спецификации позволяли типам знаковых символов иметь битовые шаблоны, которые не отображаются на число, поэтому в них отсутствовало требование о наличии 256 различных значений. «Для типов символов без знака все возможные битовые комбинации представления значения представляют собой числа. Эти требования не применяются для других типов».
Адриан Маккарти

241

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

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

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

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

И, по определению, sizeof(char)это1 , несмотря на испытания в конфигурационном скрипте Perl.

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


73
+1 за констатацию того, как обстоят дела на самом деле в делах, которые важны для большинства, а не как дела в теории. Если вы хотите использовать 32-битный тип int, если вы хотите использовать 64-битный тип long long. Если вы хотите родной, используйте size_t. Избегайте «простого» долго, потому что оно меняется. Это должно работать для большинства приложений.
Eloff

37
+1 за ответ. @Eloff: наоборот ... если вы хотите использовать 32-разрядную версию [u]int32_tили аналогичную, если вы хотите использовать 64-разрядную [u]int64_tверсию ... если у вас нет для них заголовка, загрузите или создайте его, желательно с выбором времени компиляции: такие типы или статические утверждения для проверки размера. pubs.opengroup.org/onlinepubs/009695299/basedefs/stdint.h.html Если точные размеры не так важны и вам важно только то, что они хотя бы настолько велики, то ваш совет подходит для распространенных современных ПК / серверных платформ.
Тони Делрой

8
Обратите внимание, что CHAR_BIT> 8 имеют не только старые cray-машины. Например, DSP часто имеют CHAR_BIT 16 или 32. (см., Например, эти )
nos

2
@nos: Спасибо за ссылку. Очень полезно, чтобы современные, современные системы были идентифицированы для странных случаев. Из любопытства, какой код установлен на этих машинах? Если кодовым набором является UTF-16, то 0xFFFF не является допустимым символом, а если кодовым набором является набор кодов ISO 8859-x, то снова 0xFFFF не является допустимым символом (допустимы коды символов от 0x00 до 0xFF). Я еще не уверен, что есть проблема с обнаружением EOF, но, безусловно, есть место для осторожности, и, возможно, для написания и использования функции, int get_char(FILE *fp, char *c)которая возвращает EOF или 0 и устанавливает *c.
Джонатан Леффлер

2
@joelw: C11 требует, чтобы, учитывая, uint32_t x=1,y=2;что значение x-yдолжно быть 4294967295 на платформах, где "int" равно 32 битам или меньше, и -1 на платформах, где "int" равно 33 битам или больше. Кроме того, требуется, x*yчтобы он оценивался с использованием модульной арифметики для всех значений x и y, если «int» равно 32 битам или меньше, и обычной арифметики, если 65 бит или больше, но не предъявляет никаких требований к тому, что может случиться с большими значениями. из х и у, если "int" составляет от 33 до 64 бит.
суперкат

88

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

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

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

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

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


7
хороший пост. другая вещь, которая требуется, это следующие наименьшие размеры в битах (задокументированные в c89 / c99 вместе с limit.h и принятые c ++): char> = 8, short и int> = 16, long> = 32.
Йоханнес Шауб -

1
Кроме того, на 8-битной платформе AVR size_t будет не 8 битами, а 16, потому что размеры указателя и типа int равны 16 битам. Таким образом, собственный размер данных процессора не связан с size_t.
Robotbugs

80

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

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

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

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

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

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

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

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

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

int8_t
int16_t
int32_t
int64_t

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


8
Незначительная мелочь: где стандарт говорит, sizeof(long) < sizeof(long long)а не симметрично sizeof(long) <= sizeof(long long)?
Джонатан Леффлер

2
@JonathonLeffler - см. C99 5.2.4.2.1 - Размеры целочисленных типов. minsizeof (int) == 16 бит, minsizeof (long) == 32 бит, minsizeof (long long) == 64 бит. Так что я думаю, что вы правы в <=, так как maxsizeof (тип) не указан.
Джесси Чисхолм

Аналогично sizeof (float) <= sizeof (double) <= sizeof (long double). В соответствии с C99 7.12, параграф 2.
Джесси Чисхолм

38

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


10
Они указаны, но не обязательны.
Dreamlax

2
@dreamlax Какие платформы не включают его?
Леви Моррисон

3
@LeviMorrison: Любая платформа, которая не имеет их в требуемой форме. Платформа, которая CHAR_BIT == 16, например, не будет иметь int8_t. Любая платформа, не использующая дополнение до двух, не будет иметь ни одного из них (так как стандарт требует дополнения до двух).
DevSolar

36

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

  • длинный длинный int
  • без знака long long int

И "размерные" типы из <cstdint>

  • 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 ++ 11.
Яан

2
«быстрый» означает только приспособленный к аппаратной архитектуре. Если регистры 16-битные, тогда int_fast8_t является 16-битным значением. Если регистры 32-битные, то int_fast8_t и int_fast16_t являются 32-битными значениями. и т. д. См. раздел C99 7.18.1.3, параграф 2.
Джесси Чисхолм,

19

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

3.9.1, §2:

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

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

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


12

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

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

Лучшее, что вы можете сделать, если вам нужны переменные фиксированного размера, - это использовать такие макросы:

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

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


4
Проблема в том, что WORD распространяется по программе в области, которые не зависят от фиксированного размера (посмотрите на код Windows). Как я выяснил, при переходе от 16-битной к 32-битной системе вы сталкиваетесь с той же проблемой, которую WORD должен был решить.
Лилберн

@liburne Конечно, вы должны использовать WORD только тогда, когда вам нужна переменная фиксированного размера, например, когда вы читаете / записываете из / в файл. Если фрагмент кода на самом деле не зависит от фиксированного размера, вам следует использовать обычные переменные типа int.
Эмилиано

3
Лучшее, что вы можете сделать, чтобы получить портативные размеры, должно быть#include <boost/cstdint.hpp>
kizzx2

11

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

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

typedef int int32;

int32 i;
int32 j;
...

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

typedef long int int32;

int32 i;
int32 j;
...

1
Это не обязательно, учитывая стандартный заголовок <stdint.h>(C99 и более поздние версии, и какой бы стандарт C ++ ни принимал версию C99 библиотеки C).
Кит Томпсон,

8

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


2
Однако соответствие с IEEE 754 (он же IEC 559) не является обязательным в C ++ (возможно, C тоже, но я не уверен). Смотрите std :: numeric_limits :: is_iec559.
Дрю Холл

1
Тогда вы еще не видели компилятор TI для ЦСП TMS320C28xx, где он doubleимеет одинаковый размер floatintтот же самый char, что и 16-битные). Но у них есть 64 бит long double.
звездный синий

7

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

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

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

#include <iostream>
#include <limits>


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

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

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

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



7

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

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

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


7

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

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

#include <iostream>

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

sizeof(char)не должны быть включены.
Ven

3

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


Спасибо, но я хотел бы знать размеры для архитектур, у меня нет myselft (например, 64 бит). Этот урок говорит только о 32-битных архитектурах ...
Jérôme

2

Как ответили другие, все «стандарты» оставляют большинство деталей как «определенные реализацией», и только утверждают, что тип «char» имеет ширину leat «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, но для разных платформ. Некоторые стандарты и практики (особенно limit.h и т. П.) Достаточно распространены, так что большинство компиляторов будут иметь поддержку для определения наиболее подходящего типа для определенного диапазона значений, но не количества используемых битов. (То есть, если вы знаете, что вам нужно хранить значения от 0 до 127, вы можете определить, что ваш компилятор поддерживает 8-битный тип "int8", который будет достаточно большим, чтобы содержать полный требуемый диапазон, но не как Тип "int7", который будет точным совпадением для 7-бит.)

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


1

Если вы заинтересованы в чистом решении 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, также объявленный в этом заголовке.

Код, указанный ниже, предоставляется без гарантии, пожалуйста, проверьте его.
Я новичок в METAPROGRAMMING TOO, не стесняйтесь редактировать и исправлять этот код.
Протестировано с DevC ++ (так что версия gcc около 3.5)

#include <limits>

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<T,S> type
     *
     *  Example:
     *   Creating a list with type int and char: 
     *      typedef type_list<int, type_list<char> > test;
     *      test::value         //int
     *      test::next::value   //char
     */
    template <typename T, typename S> struct type_list
    {
        typedef T value;
        typedef S next;         

    };




    /*
     * Declaration of template struct for selecting a type from the list
     */
    template <typename list, int b, int ctl> struct select_type;


    /*
     * Find a type with specified "b" bit in list "list"
     *
     * 
     */
    template <typename list, int b> 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<cur_type>::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<list, b, cur_type_bits>::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 <int b> struct find_type<null_type, b>
    {   
        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 <typename list, int b, int ctl> struct select_type
    {   
            typedef  typename find_type<typename list::next, b>::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 <typename list, int b> struct select_type<list, b, b>
    {
            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<unsigned char,         \
        type_list<unsigned short,                           \
        type_list<unsigned int,                             \
        type_list<unsigned long,                            \
        type_list<unsigned long long, null_type> > > > >

    #define SIGNED_TYPES type_list<signed char,         \
        type_list<signed short,                         \
        type_list<signed int,                           \
        type_list<signed long,                          \
        type_list<signed long long, null_type> > > > >



    /*
     * 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<UNSIGNED_TYPES, 8>::type  uint8;
    typedef find_type<UNSIGNED_TYPES, 16>::type uint16;
    typedef find_type<UNSIGNED_TYPES, 32>::type uint32;
    typedef find_type<UNSIGNED_TYPES, 64>::type uint64;

    typedef find_type<SIGNED_TYPES, 7>::type    int8;
    typedef find_type<SIGNED_TYPES, 15>::type   int16;
    typedef find_type<SIGNED_TYPES, 31>::type   int32;
    typedef find_type<SIGNED_TYPES, 63>::type   int64;

}

0
unsigned char bits = sizeof(X) << 3;

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


1
символ не всегда 8 бит, поэтому ваше выражение не будет работать на архитектурах с не 8-битным символом . Только sizeof(type)*CHAR_BITдержит
phuclv

Даже если CHAR_BITбыло гарантировано 8 бит, << 3это просто запутанный способ записи * 8или * CHAR_BIT.
Кит Томпсон

0

От Алекса Б. Стандарт C ++ не определяет размер целочисленных типов в байтах, но он определяет минимальные диапазоны, которые они должны иметь. Вы можете вывести минимальный размер в битах из необходимого диапазона. Из этого можно определить минимальный размер в байтах и ​​значение макроса CHAR_BIT, который определяет количество бит в байте (во всех, кроме самых непонятных платформ, это 8, и оно не может быть меньше 8).

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

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

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

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

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

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

C:

#include <limits.h>
const int min_int = INT_MIN;
const int max_int = INT_MAX;

C ++:

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

Это правильно, однако вы также правы, говоря: char: 1 байт короткий: 2 байта int: 4 байта длиной: 4 байта с плавающей запятой: 4 байта double: 8 байтов

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

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


0

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

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

  • Половинная точность (двоичная16) - 11-битное значение, диапазон экспонент от -14 до 15
  • Одинарная точность (двоичная32) - 24-битное значение, диапазон экспонент от -126 до 127
  • Двойная точность (двоичная64) - 53-разрядное значение, диапазон экспонент от -1022 до 1023
  • Четверная точность (двоичная 128) - 113-разрядное значение, диапазон экспонент от -16382 до 16383

Как это соотносится с типами C ++? Обычно floatиспользуется одинарная точность; Таким образом, sizeof(float) = 4. Затем doubleиспользуется двойная точность (я полагаю, это источник названия double), и long doubleможет быть двойной или четырехкратной точности (в моей системе она в четыре раза, но в 32-битных системах она может быть двойной). Я не знаю ни одного компилятора, который предлагал бы с плавающей точкой половинной точности.

Подводя итог, это обычно:

  • sizeof(float) = 4
  • sizeof(double) = 8
  • sizeof(long double) = 8 или 16

Забавно, что я пришел к этому вопросу как часть удивления, почему Джефф использует больше байтов, чем ему нужно.
Анируддха Варма


-2

Вы можете использовать переменные, предоставляемые библиотеками, такими как OpenGL , Qt и т. Д.

Например, Qt предоставляет qint8 (гарантированно 8-битный на всех платформах, поддерживаемых Qt), qint16, qint32, qint64, quint8, quint16, quint32, quint64 и т. Д.


1
Не отвечает на вопрос
EvilTeach

-8

На 64-битной машине:

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

2
На некоторых 64-битных машинах intэто 8 байтов, но другой не гарантируется. Там нет ничего, что говорит, что charдолжно быть только 8 бит. Это разрешено иметь, sizeof(void*)==4хотя это 64 бит.
скайкинг

-10

Существует четыре типа целых чисел в зависимости от размера:

  • короткое целое число: 2 байта
  • длинное целое число: 4 байта
  • long long integer: 8 байт
  • целое число: зависит от компилятора (16-битный, 32-битный или 64-битный)

11
Ложь, все они зависят от архитектуры, с минимальными диапазонами, описанными в одном из других ответов. Ничто не мешает реализации short, intи longвсе 32-битные целые числа.
Matteo Italia

Вы даже не использовали правильные имена для типов. В именах используется ключевое слово int, а не слово «целое число».
Кит Томпсон
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.