В чем разница между int и long в C ++?

120

Поправьте меня, если я ошибаюсь,

int - 4 байта с диапазоном значений от -2 147 483 648 до 2 147 483 647 (2 ^ 31)
long - 4 байта с диапазоном значений от -2 147 483 648 до 2 147 483 647 (2 ^ 31)

В чем разница в C ++? Могут ли они использоваться как взаимозаменяемые?

Joel
источник
В моем VS2005, работающем на 32-битном процессоре, размер int по умолчанию составляет 4 байта.
Если вы хотите написать переносимый код, подумайте об использовании, #include <stdint.h>а затем типов, которые определяют размер. Напр uint32_t. На новой платформе вам нужно только убедиться, что stdint.h подходит для этой конкретной платформы, и ваш код работает должным образом.
BitTickler

Ответы:

112

Это зависит от реализации.

Например, в Windows они такие же, но, например, в системах Alpha long было 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 07
2
Некоторые компиляторы даже имеют флаги, которые позволяют вам изменять размер по умолчанию для int и long, то есть устанавливать их на 8 или 16 и т. Д. За подробностями обращайтесь к документации по компилятору.
Мартин Йорк,
7
NB, что это размеры 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 (short)> = sizeof (char), мы знаем только, что sizeof (short)> = 1 (не> = 2), что, кстати, относится ко всем типам. Согласно этому sizeof (любой интегральный тип)> = 1. Что верно, например, я помню sizeof (int) == 1 на Z80, но нет ли более надежной гарантии на долгое время?
Андреас Магнуссон
6
3.9.1.2 стандарта C ++ указывает, что sizeof (long)> = sizeof (int)> = sizeof (short)> = sizeof (char). 5.3.3.1 стандарта C ++ указывает, что sizeof (char), sizeof (unsigned char) , а sizeof (знаковый символ) равен 1. (продолжение ...)
KTC
4
(... продолжение) Максимальные и минимальные значения, представленные интегральными типами, определены как макросы в <limits.h> (и, следовательно, <climits>). Приложение E к стандарту C (1990), которое включено в качестве ссылки из стандарта C ++, определяет минимальные значения этих макросов. (продолжение ...)
KTC
4
(... cont) и они равны (2 ^ 15) -1, (2 ^ 15) -1, (2 ^ 31) -1, для краткости, int и long соответственно, что оказывается значением как отправленный Мартином Йорком в его ответе здесь, если CHAR_BIT равен 8 (что также является его минимальным значением).
KTC
2
@Giles: Разве это не то, что я сказал выше? sizeof (short) * CHAR_BITS> = 16. Добавьте еще несколько вещей. :-)
Мартин Йорк
13

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

GCC использует модель LP64, что означает, что целые числа являются 32-битными, а длинные - 64-битными в 64-битном режиме.

Например, MSVC использует модель LLP64, что означает, что как целые, так и длинные числа являются 32-битными даже в 64-битном режиме.

Адриан
источник
возможно 0 байт? хмм
rogerdpack
12

Сама спецификация C ++ (старая версия, но достаточно хорошая для этого) оставляет это открытым.

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

[Сноска: то есть достаточно большой, чтобы содержать любое значение в диапазоне INT_MIN и INT_MAX, как определено в заголовке <climits>. --- конец foonote]

Кевин Хейнс
источник
7

Как указывает Кевин Хейнс, целые числа имеют естественный размер, предлагаемый средой выполнения, который должен соответствовать INT_MIN и INT_MAX.

В стандарте C89 указано, что UINT_MAXдолжно быть не менее 2 ^ 16-1, USHRT_MAX2 ^ 16-1 и ULONG_MAX2 ^ 32-1. Это составляет не менее 16 бит для коротких и целых чисел и 32 для длинных. Для char он явно указывает, что он должен иметь не менее 8 бит ( CHAR_BIT). C ++ наследует эти правила для файла limits.h, поэтому в C ++ у нас те же основные требования к этим значениям. Вы должны , однако не проистекают из того что ИНТ по крайней мере , 2 байта. Теоретически char, int и long могут быть 1 байтом, и в этом случае CHAR_BITдолжно быть не менее 32. Просто помните, что «байт» всегда равен размеру char, поэтому, если char больше, байт - это не только 8 бит. Больше.

Йоханнес Шауб - litb
источник
Я не думал, что byteтип данных существует в C ++. Нет, не так ли? Если это так, а byteразмер a может отличаться от 8 бит, это просто глупо. Почему они назвали его байтом, если это не обязательно 8 бит?
Alderath 02
6

Это зависит от вашего компилятора. Вам гарантируется, что long будет как минимум такого же размера, как int, но вам не гарантируется, что он будет больше.

Андру Лувиси
источник
5

По большей части количество байтов и диапазон значений определяется архитектурой ЦП, а не C ++. Однако C ++ устанавливает минимальные требования, которые подробно объяснены, а Мартин Йорк допустил лишь несколько ошибок.

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

Программист Windows
источник
5

Если вы когда-нибудь компилируете свой код на другой машинной архитектуре, ОС или компиляторе другого поставщика, то полагаться на реализацию поставщика компилятора примитивных размеров типов БУДЕТ преследовать вас.

Большинство поставщиков компиляторов предоставляют файл заголовка, который определяет примитивные типы с явными размерами типов. Эти примитивные типы следует использовать, когда код потенциально может быть перенесен на другой компилятор (читайте это ВСЕГДА в КАЖДОМ экземпляре). Например, у большинства компиляторов 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 требует, чтобы определения типов, которые выглядели как int32_t, uint64_t и т. Д., Определялись компилятором и имели ровно столько битов, сколько следует из названия. Большинство компиляторов C ++ (включая g ++) позволяют использовать эти константы в коде C ++.
rmeador
5

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

3.9.1, §2:

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

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

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

Жером Радикс
источник