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

210

Я перехожу с Java на C ++ и у меня есть несколько вопросов о longтипе данных. В Java, чтобы держать целое число больше 2 32 , вы просто пишете long x;. Однако в C ++ кажется, что longэто и тип данных, и модификатор.

Кажется, есть несколько способов использования long:

long x;
long long x;
long int x;
long long int x;

Кроме того, кажется, есть такие вещи, как:

long double x;

и так далее.

В чем разница между всеми этими различными типами данных и имеют ли они одну и ту же цель?

1110101001
источник
2
@ user2612743 - чтобы быть в безопасности, подумайте о ваших требованиях и используйте соответствующий тип. long longможет быть медленнее, чем long, который может быть медленнее, чем int.
Пит Беккер
1
Нет, «быть в безопасности, использовать долго, долго» - это то же самое, что сказать «быть в безопасности, просто дать всем один земной СПИД, чтобы нам не приходилось беспокоиться о безопасном сексе, мы все равно уже получили его!» Глупо, нет? Подумайте о данных и возможных значениях, которые они могут иметь, и используйте наиболее подходящий тип. Это также помогает компилятору выполнять дополнительную оптимизацию, не нарушая намерения исходного кода, например, если ему необходимо загрузить дополнительные библиотеки для обработки чисел, превышающих естественную ширину в битах целевой платформы.
СМ
Использование long long со списками win32 и т. П. Не имеет смысла разрушать вашу память и другие переменные, даже если ограничения не нарушены. Даже с безобидными предупреждениями C4244 это не так легко обнаружить.
Лори Стерн

Ответы:

182

longи long intидентичны. Так long longи есть long long int. В обоих случаях intопционально.

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

Контролирующие части стандарта (C ++ 11, но это было давно), например 3.9.1 Fundamental types, раздел 2 (в следующем разделе приведены аналогичные правила для целых типов без знака):

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

Также есть таблица 9 7.1.6.2 Simple type specifiers, которая показывает «сопоставления» спецификаторов с реальными типами (показывая, что intэто необязательно), раздел которых показан ниже:

Specifier(s)         Type
-------------    -------------
long long int    long long int
long long        long long int
long int         long int
long             long int

Обратите внимание на различие между спецификатором и типом. Спецификатор - это то, как вы сообщаете компилятору, что это за тип, но вы можете использовать разные спецификаторы, чтобы получить один и тот же тип.

Следовательно, сам longпо себе не является ни типом, ни модификатором, как предполагает ваш вопрос, это просто спецификатор для long intтипа. То же long longсамое для спецификатора long long intтипа.

Хотя сам стандарт C ++ не определяет минимальные диапазоны целочисленных типов, он ссылается на C99 в 1.2 Normative referencesкачестве применяемого. Следовательно, минимальные диапазоны, изложенные в C99 5.2.4.2.1 Sizes of integer types <limits.h>, применимы.


С точки зрения long double, это на самом деле значение с плавающей запятой, а не целое число. Как и в случае целочисленных типов, требуется иметь как минимум такую ​​же точность, как и, doubleи предоставлять надмножество значений для этого типа (то есть, по крайней мере, те значения, а не обязательно больше значений).

paxdiablo
источник
4
То же самое с unsignedиunsigned int
Кал
2
Я уверен, что longпо крайней мере 32 бита (2 ^ 31-1 по обе стороны от нуля) и long longпо крайней мере 64 (2 ^ 63-1 по обе стороны).
Крис
2
И long doubleгарантированно иметь хотя бы диапазон double, но он может быть таким же. Это зависит от компьютера. Некоторые FPU обладают повышенной точностью; Чипы x87 имели 32-битную одинарную точность, 64-битную двойную точность и 80-битную расширенную точность.
Эрик Джаблоу,
Что касается требований диапазона, стандарт C ++ 11 ссылается на стандарт C11, который имеет фактические диапазоны.
Крис
Часть «int» просто различает целочисленный тип и тип с плавающей запятой, символ или другой нецелочисленный тип. Во многих случаях это может быть выведено компилятором, поэтому его можно отбросить - вот почему «unsigned», например, так же, как «unsigned int». Часть «int» просто предполагается, если только программист не укажет что-то еще, например, «char» или «double». Что касается фактических используемых размеров ... в зависимости от того, какой стандарт вы читаете, каждый размер может иметь минимальное количество битов, но все они определены так, что каждый из них, по крайней мере, такой же большой, как и предыдущий тип.
СМ
17

longэквивалентно long int, так же, как shortэквивалентно short int. A long intпредставляет собой целочисленный тип со знаком, который составляет по меньшей мере 32 бита, в то время как целочисленный тип со знакомlong long или long long intпредставляет собой по меньшей мере 64 бита.

Это не обязательно означает, что а long longшире long. Многие платформы / ABI используют LP64модель - где long(и указатели) имеют ширину 64 бита. Win64 использует LLP64, где longвсе еще 32 бита, и long long(и указатели) имеют ширину 64 бита.

Там хороший обзор моделей 64-разрядных данных здесь .

long doubleне гарантирует ничего, кроме того, что он будет по крайней мере таким же широким, как и double.

Бретт Хейл
источник
7

Это выглядит сбивающим с толку, потому что вы используете longсам тип данных.

longэто всего лишь стенография, long intкогда вы используете его в одиночку.

longэто модификатор, вы можете использовать его doubleтакже как long double.

long== long int.

Оба они занимают 4 байта.

Сирадж Алам
источник
Длинные 4 байта действительны только для Win64, они зависят от платформы
Prodigle
1
Да, очевидно ... не только long ... int занимает 4 байта и 2 байта зависят от платформы, без сомнения.
Сирадж Алам
3

Исторически, в ранние времена C, когда процессоры имели длину слова 8 или 16 бит, intбыли идентичны сегодняшним short(16 битам). В определенном смысле, внутр является более абстрактным типом данных , чем char, short, longили long long, как вы не можете быть уверены в битовой.

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

[Правка: #include <stdint.h>кажется правильным способом обеспечения битовой пропускной способности с использованием типов int ## _ t, хотя это еще не является частью стандарта.]

thomiel
источник
2
Последняя часть, использующая «long» для получения 32-битных, когда int 64-битная, неверна. Если int является 64-битным, то long будет также по крайней мере 64-битным. Long гарантированно будет по крайней мере таким же большим, как int, хотя он может быть больше, но никогда не меньше. Большинство компиляторов имеют различные методы, которые позволяют программисту быть более конкретным, такие как (непереносимый) тип __int32, который является точно 32-битным, и так далее.
СМ
1
Как определено в стандарте C, longгарантированно , что a должно быть не менее 32 бит. (Стандарты могут измениться жестко.) В текущем проекте C ++ 14 просто сказано: @CM «Простые целые имеют естественный размер, предложенный архитектурой среды выполнения, остальные целочисленные типы со знаком предоставляются для удовлетворения особых потребностей» (раздел 3.9.1 ). Я не нашел ни слова о соотношении длин различных целых в нем. __int32 на самом деле не является частью стандарта, но, начиная с C ++ 11, доступны определения типов, такие как int_fast32_t или int_least32_t, чтобы получить именно то, что вы хотите.
Томель
Я бы сказал, что в реализациях двадцатого века для перепрограммируемых микрокомпьютеров общего назначения charбыло почти единодушно 8 битов, short16 и long32; intможет быть 16 или 32. Обратите внимание, что для некоторых платформ (особенно 68000) как 16-битные, так и 32-битные intбыли довольно распространены, и действительно, некоторые компиляторы имели варианты поддержки либо. Таким образом, ожидается, что код, который должен быть переносимым, будет использовать shortили longпредпочтительнее int.
суперкат
0

В то время как в Java longвсегда 64 бит, в C ++ это зависит от архитектуры компьютера и операционной системы . Например, a long- это 64-битная версия в Linux и 32-битная версия в Windows (это было сделано для обеспечения обратной совместимости, позволяя 32-битным программам компилироваться в 64-битной Windows без каких-либо изменений).

Это считается хорошим стилем C ++, чтобы избежать short int long ... и вместо этого использовать:

std::int8_t   # exactly  8 bits
std::int16_t  # exactly 16 bits
std::int32_t  # exactly 32 bits
std::int64_t  # exactly 64 bits

std::size_t   # can hold all possible object sizes, used for indexing

Эти ( int*_t) могут быть использованы после включения <cstdint>заголовка. size_tнаходится в <stdlib.h>.

xjcl
источник