Який стандарт C ++ визначає розмір int, довгий тип?


696

Я шукаю детальну інформацію про розмір основних типів 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). між. Якщо розмір int є таким важливим, який можна використовувати 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
@ Програмер Прочитайте відповідь (пункт 1 примітка в дужках) або власне формулювання стандарту (пов'язане у відповіді). Стандарт C вміщує 1 архітектуру доповнення 1, яка відрізняється від найпоширенішого доповнення 2-х. Мінімальні гарантовані діапазони майже завжди відрізнятимуться від фактичних діапазонів, які надає реалізація.
Алекс Б

9
@ Алекс Б у своїй відповіді ви нічого не згадували про подвійне. Чи можете ви оновити відповідь щодо змінних з плаваючою комою?
Cool_Coder

3
@Cool_Coder: Плаваюча точка - це цілий додатковий чайник з рибою, який легко подвоює розмір постів.
Дедуплікатор

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

241

Для 32-бітових систем стандартним фактором є фактично ILP32 - тобто int, longа покажчик - це всі 32-бітні величини.

Для 64-бітних систем основним стандартом Unix 'de facto' є LP64 - longа вказівник 64-розрядний (але intє 32-розрядним). 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-бітове використання було довгим. Якщо ви хочете, використовуйте size_t. Уникайте "простого" довго, тому що воно змінюється. Це повинно працювати для більшості програм.
Елоф

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

8
Зауважте, що це не лише старі крашанки, які мають CHAR_BIT> 8. Наприклад, DSP часто мають CHAR_BIT 16 або 32. (див., Наприклад, ці )

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 біт або більше, але не ставить жодних вимог щодо того, що може статися з великими значеннями з x і y, якщо "int" - від 33 до 64 біт.
supercat

88

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

Що стосується всіх інших вбудованих типів, це дійсно залежить від компілятора. Ось два уривки, взяті з поточного робочого проекту останнього стандарту C ++:

Існує п’ять стандартних цілих цілих типів: підписаний знак char, короткий int, int, long int і long long int. У цьому списку кожен тип забезпечує принаймні стільки пам’яті, скільки й тих, що передують йому в списку.

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

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


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

1
Крім того, на 8-бітній платформі AVR size_t збирається не 8 біт, а 16, тому що розміри вказівника та int - це 16 біт. Отже розмір нативних даних процесора не пов'язаний з size_t.
Роботи

80

Є стандарт.

Стандарт C90 цього вимагає

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

Стандарт С99 цього вимагає

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 (довгий) == 32-біт, minsizeof (long long) == 64-біт. Тому я думаю, що ви праві на <=, оскільки не вказано maxsizeof (тип).
Джессі Чизгольм

Аналогічно sizeof (float) <= sizeof (подвійний) <= sizeof (довгий подвійний). Згідно з пунктом 2. C99 7.12
Джессі Чизгольм

38

Якщо вам потрібні типи фіксованого розміру, використовуйте такі типи, як uint32_t (непідписане ціле число 32 біта), визначені в stdint.h . Вони вказані в С99 .


10
Вони вказані, але не обов'язкові.
dreamlax

2
@dreamlax Які платформи не включають його?
Леві Моррісон

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

36

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

  • довгий довгий int
  • неподписаний довгий довгий 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-бітовими значеннями. та ін. Див. розділ 2. C99, розділ 7.18.1.3
Джессі

19

Стандарт C ++ говорить про це так:

3.9.1, §2:

Існує п'ять підписаних цілих типів: "підписаний char", "short 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 мав вирішити.
lilburne

@liburne Звичайно, ви повинні використовувати WORD лише тоді, коли вам потрібна змінна розмір фіксованого розміру, наприклад, коли ви читаєте / пишете з / у файл. Якщо фрагмент коду насправді не залежить від фіксованого розміру, то слід використовувати звичайні змінні "int".
Еміліано

3
Найкраще, що ви можете зробити для отримання портативних розмірів, має бути#include <boost/cstdint.hpp>
kizzx2

11

Нам дозволяється визначати синонім типу, щоб ми могли створити власний "стандарт".

На машині, розмір якої (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 бібліотеки C99).
Кіт Томпсон

8

Для чисел з плаваючою комою існує стандарт (IEEE754) : поплавці є 32-бітовими, а подвійні - 64. Це стандарт обладнання, а не стандарт C ++, тому компілятори теоретично могли б визначати float і double до якогось іншого розміру, але на практиці я ' я ніколи не бачив архітектури, яка використовувала щось інше.


2
Однак, відповідність IEEE 754 (він же IEC 559) є необов’язковим у межах C ++ (можливо, також C, але я не впевнений). Див. Std :: numeric_limits :: is_iec559.
Дрю Холл

1
Тоді ви ще не бачили компілятора TI для DSP TMS320C28xx, де doubleмає той самий розмір, що і floatintтакий же, як charобидва - 16 бітові). Але у них 64 біт long double.
starblue

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-бітний г ++ 4.7.3 вихід. Також врахуйте, на що відповіли нижче, чому результат впорядковується як такий:

"Існує п'ять стандартних цілих цілих типів: підписаний знак char, короткий 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)не слід включати.
Вень

3

Як зазначалося, розмір повинен відображати поточну архітектуру. Ви можете досягти піку, limits.hякщо хочете побачити, як ваш поточний компілятор обробляє речі.


Дякую, але я хотів би знати розміри для архітектури, у мене немає myselft (наприклад, 64 біт). У цьому підручнику йдеться лише про 32-бітну архітектуру ...
Jérôme

2

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

Частина причин того, що не мають дуже конкретних і точних значень, полягає в тому, що такі мови, як 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, також оголошеному в цьому заголовку.

КОД, ВИНАГАЛЬНИЙ, ПОДАЄТЬСЯ БЕЗ ГАРАНТІЇ, МОЛУЙТЕ ДВОЙСЬКУ ВИСТАВКУ.
Я НОВИЙ В МЕТРАПРОГРАММУВАННІ ТАК, БУДУТЬСЯ БЕЗКОШТОВНО ВИПРАВИТИ ТА ВРАЖИТИ ЦИЙ КОД.
Тестується за допомогою 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
char - це не завжди 8 біт, тому ваше вираження не буде працювати в архітектурах з не-8-бітовими символами . Лише sizeof(type)*CHAR_BITутримується
phuclv

Навіть якщо б CHAR_BITгарантовано склали 8 біт, << 3це просто неясний спосіб написання * 8або * CHAR_BIT.
Кіт Томпсон

0

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

Додатковим обмеженням для char є те, що його розмір завжди становить 1 байт або CHAR_BIT біт (звідси назва).

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

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

підписаний знак: від -127 до 127 (зауважте, не -128 до 127; це вміщує платформи з 1 доповненням) без підпису char: 0 до 255 "звичайний" char: від -127 до 127 або 0 до 255 (залежить від підписання символу за замовчуванням) короткий: від 32767 до 32767 без підпису короткий: від 0 до 65535, підписаний int: від -32767 до 32767, без підписаного int: від 0 до 65535, підписаний довго: -2147483647 до 2147483647, без підпису, довгий: від 0 до 4294967295, з довгим підписом: -9223372036854775807 до 922337803685, з 922337203685 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 байти подвійні: 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 байти
  • довге довге ціле число: 8 байт
  • ціле число: залежить від компілятора (16 біт, 32 біт або 64 біт)

11
Помилково, всі вони залежать від архітектури, при цьому мінімальні діапазони описані в одній з інших відповідей. Ніщо не зупиняє реалізацію , щоб мати short, intі longвсі 32 - бітні цілі числа.
Маттео Італія

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