Яка різниця між int і long у C ++?


120

Виправте мене, якщо я помиляюся,

int - 4 байти, діапазон значень від -2,147,483,648 до 2,147,483,647 (2 ^ 31)
довжиною становить 4 байти, діапазон значень від -2,147,483,648 до 2,147,483,647 (2 ^ 31)

Чим відрізняється C ++? Чи можна їх взаємозамінно використовувати?


У моєму VS2005, який працює на 32-бітовому процесорі, розмір за замовчуванням int становить 4 байти.


Якщо ви хочете написати портативний код, подумайте про використання, #include <stdint.h>а потім типи, які визначають розмір. Напр uint32_t. На новій платформі вам потрібно лише переконатися, що stdint.h підходить саме до цієї платформи, і ваш код працює за призначенням.
BitTickler

Відповіді:


112

Це залежить від реалізації.

Наприклад, для Windows вони однакові, але, наприклад, у Альфа-системах, довгий був 64 біт, тоді як int - 32 біт. У цій статті висвітлюються правила для компілятора Intel C ++ на змінних платформах. Узагальнити:

  OS           arch           size
Windows       IA-32        4 bytes
Windows       Intel 64     4 bytes
Windows       IA-64        4 bytes
Linux         IA-32        4 bytes
Linux         Intel 64     8 bytes
Linux         IA-64        8 bytes
Mac OS X      IA-32        4 bytes
Mac OS X      Intel 64     8 bytes  

Я думаю, що ми повинні розглянути можливість поєднання цієї відповіді (відповідь на прикладі) з деякими деталями нижче щодо стандарту C ++. Проект для C ++ 0x знаходиться на веб- сайті open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2798.pdf, і він позначений, щоб ви могли побачити відмінності між ним та останнім числом оборотів.
Патрік Джонмайєр

Якщо включити щось у відносному порядку розміру типів, то це дає більше інформації, ніж перерахування розмірів для різних платформ, як-от @Kevin так добре. (-1воте)
xtofl

2
Деякі компілятори навіть мають прапори, які дозволяють змінювати розмір за замовчуванням int і long, тобто змушувати їх до 8 чи 16 тощо. Детальну інформацію див. У документації щодо компілятора.
Мартін Йорк

7
Зверніть увагу, що це розміри long
rogerdpack

1
Будь ласка, включіть також розміри int.
cegprakash

82

Єдина гарантія, яку ви маєте:

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

// FROM @KTC. The C++ standard also has:
sizeof(signed char)   == 1
sizeof(unsigned char) == 1

// NOTE: These size are not specified explicitly in the standard.
//       They are implied by the minimum/maximum values that MUST be supported
//       for the type. These limits are defined in limits.h
sizeof(short)     * CHAR_BIT >= 16
sizeof(int)       * CHAR_BIT >= 16
sizeof(long)      * CHAR_BIT >= 32
sizeof(long long) * CHAR_BIT >= 64
CHAR_BIT         >= 8   // Number of bits in a byte

Дивіться також: Є чи longгарантовано бути принаймні 32 біта?


1
Хм, це не відповідає, якщо sizeof (короткий)> = sizeof (char) ми знаємо лише той sizeof (короткий)> = 1 (not> = 2), який btw застосовується для всіх типів. Відповідно до цього sizeof (будь-якого інтегрального типу)> = 1. Що вірно, наприклад, я пам’ятаю sizeof (int) == 1 на Z80, але чи немає більш міцної гарантії на тривалий час?
Андреас Магнуссон

6
3.9.1.2 стандарту C ++ вказати, що sizeof (довгий)> = sizeof (int)> = sizeof (короткий)> = sizeof (char) 5.3.3.1 стандарту C ++ вказати, що sizeof (char), sizeof (неподписаний знак) , а розмір (підписаний знак) дорівнює 1. (продовження ...)
KTC

4
(... продовження) Максимальні та мінімальні значення, представлені інтегральними типами, визначаються як макроси в <limit.h> (і, отже, <climits>). У Додатку Е стандарту C (1990), які включені посиланням зі стандарту С ++, вказуються мінімальні величини цих макросів. (продовження ...)
KTC

4
(... продовження), і вони (2 ^ 15) -1, (2 ^ 15) -1, (2 ^ 31) -1, для коротких, int і довгих відповідно, що виявляється значенням як розміщений Мартином Йорком у своїй відповіді тут, якщо CHAR_BIT дорівнює 8 (що також є його мінімальним значенням).
КТК

2
@Giles: Це не те, про що я говорив вище? sizeof (короткий) * CHAR_BITS> = 16. Вставте кілька інших речей. :-)
Мартін Йорк

13

Під час компіляції для x64 різниця між int та long становить десь від 0 до 4 байтів, залежно від того, який компілятор ви використовуєте.

GCC використовує модель LP64, що означає, що вбудовані символи є 32-бітними, а довгі - 64-бітними в 64-бітному режимі.

Наприклад, MSVC використовує модель LLP64, що означає, що і int, і long - 32-бітні навіть у 64-бітному режимі.


можливо 0 байт? хм
rogerdpack

12

Сама специфікація C ++ (стара версія, але досить хороша для цього) залишає це відкритим.

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

[Зноска: тобто досить велика, щоб містити будь-яке значення в діапазоні INT_MIN та INT_MAX, як визначено у заголовку <climits>. --- кінцева сторона]


7

Як зазначає Кевін Хейнс, інти мають природний розмір, запропонований середовищем виконання, який повинен відповідати INT_MIN та INT_MAX.

Стандарт C89 визначає, що UINT_MAXмає бути принаймні 2 ^ 16-1, USHRT_MAX2 ^ 16-1 та ULONG_MAX2 ^ 32-1. Це робить розрядку принаймні 16 принаймні 16 для коротких і int, і 32 для довгих. Для char чітко зазначено, що він повинен мати принаймні 8 біт ( CHAR_BIT). C ++ успадковує ці правила для файлу limit.h, тому в C ++ у нас є однакові основні вимоги до цих значень. Однак ви не повинні випливати з того, що int принаймні 2 байти. Теоретично, char, int і long можуть становити 1 байт, і в цьому випадку CHAR_BITповинно бути принаймні 32. Пам'ятайте лише, що "байт" завжди є розміром char, тому якщо char більше, то байт не є лише 8 біт будь-яким більше.


Я не думав, що byteтип даних існує в C ++. Це не так, чи не так? Якщо це так, і byteможе мати інші розміри, ніж 8 біт, це просто чисто дурно. Чому б вони називали його байтом, якщо це абсолютно не обов'язково 8 біт?
Alderath

6

Це залежить від вашого компілятора. Вам гарантовано, що довго буде як мінімум таким же великим, як інт, але ви не гарантуєте, що воно буде більше.


5

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

Причина, по якій ви не можете використовувати взаємозамінні int та long, полягає в тому, що вони не завжди однакової довжини. C був винайдений на PDP-11, де байт мав 8 біт, int - два байти і ним можна було керувати безпосередньо за допомогою апаратних інструкцій. Оскільки програмістам C часто потрібна арифметика чотирьох байтів, довго було винайдено, і це чотири байти, якими керували функції бібліотеки. Інші машини мали різні технічні характеристики. Стандарт С встановлює деякі мінімальні вимоги.


5

Спираючись на реалізацію примітивом типових розмірів постачальника компілятора, ЗНО буде переслідувати вас, якщо ви коли-небудь компілюєте свій код на іншій архітектурі машини, ОС або іншому компіляторі постачальника.

Більшість постачальників компіляторів надають файл заголовка, який визначає примітивні типи з розмірами типу explict. Ці примітивні типи слід використовувати, коли коли-небудь код може бути потенційно перенесений на інший компілятор (читайте це ЗАВЖДИ в кожному випадку). Наприклад, у більшості компіляторів UNIX є int8_t uint8_t int16_t int32_t uint32_t. Microsoft має INT8 UINT8 INT16 UINT16 INT32 UINT32. Я віддаю перевагу Borland / CodeGear's int8 uint8 int16 uint16 int32 uint32. Ці назви також трохи нагадують про розмір / діапазон призначеного значення.

Протягом багатьох років я використовував явні прімітивні назви типу Borland та #includeнаступний заголовок C / C ++ (primitive.h), який призначений для визначення явних примітивних типів із цими іменами для будь-якого компілятора C / C ++ (цей файл заголовка може насправді не охоплювати кожного компілятор, але він охоплює декілька компіляторів, які я використовував у Windows, UNIX та Linux, він також не (ще) не визначає 64-ти бітні типи).

#ifndef primitiveH
#define primitiveH
// Header file primitive.h
// Primitive types
// For C and/or C++
// This header file is intended to define a set of primitive types
// that will always be the same number bytes on any operating operating systems
// and/or for several popular C/C++ compiler vendors.
// Currently the type definitions cover:
// Windows (16 or 32 bit)
// Linux
// UNIX (HP/US, Solaris)
// And the following compiler vendors
// Microsoft, Borland/Imprise/CodeGear, SunStudio,  HP/UX
// (maybe GNU C/C++)
// This does not currently include 64bit primitives.
#define float64 double
#define float32 float
// Some old C++ compilers didn't have bool type
// If your compiler does not have bool then add   emulate_bool
// to your command line -D option or defined macros.
#ifdef emulate_bool
#   ifdef TVISION
#     define bool int
#     define true 1
#     define false 0
#   else
#     ifdef __BCPLUSPLUS__
      //BC++ bool type not available until 5.0
#        define BI_NO_BOOL
#        include <classlib/defs.h>
#     else
#        define bool int
#        define true 1
#        define false 0
#     endif
#  endif
#endif
#ifdef __BCPLUSPLUS__
#  include <systypes.h>
#else
#  ifdef unix
#     ifdef hpux
#        include <sys/_inttypes.h>
#     endif
#     ifdef sun
#        include <sys/int_types.h>
#     endif
#     ifdef linux
#        include <idna.h>
#     endif
#     define int8 int8_t
#     define uint8 uint8_t
#     define int16 int16_t
#     define int32 int32_t
#     define uint16 uint16_t
#     define uint32 uint32_t
#  else
#     ifdef  _MSC_VER
#        include <BaseTSD.h>
#        define int8 INT8
#        define uint8 UINT8
#        define int16 INT16
#        define int32 INT32
#        define uint16 UINT16
#        define uint32 UINT32
#     else
#        ifndef OWL6
//          OWL version 6 already defines these types
#           define int8 char
#           define uint8 unsigned char
#           ifdef __WIN32_
#              define int16 short int
#              define int32 long
#              define uint16 unsigned short int
#              define uint32 unsigned long
#           else
#              define int16 int
#              define int32 long
#              define uint16 unsigned int
#              define uint32 unsigned long
#           endif
#        endif
#      endif
#  endif
#endif
typedef int8   sint8;
typedef int16  sint16;
typedef int32  sint32;
typedef uint8  nat8;
typedef uint16 nat16;
typedef uint32 nat32;
typedef const char * cASCIIz;    // constant null terminated char array
typedef char *       ASCIIz;     // null terminated char array
#endif
//primitive.h

C99 мандатує, що typedefs, схожі на int32_t, uint64_t, тощо, визначаються компілятором і мають рівно стільки бітів, скільки підказує ім'я. Більшість компіляторів C ++ (включаючи g ++) дозволять використовувати ці константи в коді C ++.
rmeador

5

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

3.9.1, §2:

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

(44), тобто достатньо великий, щоб містити будь-яке значення в діапазоні INT_MIN та INT_MAX, як визначено у заголовку <climits> .

Висновок: залежить від того, над якою архітектурою ви працюєте. Будь-яке інше припущення хибне.

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