Зачем нужен тип long когда есть int?

366
15 февраля 2017, 22:57

В С есть тип long. Согласно: Wiki c-types он занимет в памяти 4 байта, да и диапазон значений у него такой же как и у int. Тогда зачем он нужен?

Выписка из wiki:

int:

Основной тип целого числа со знаком. Может содержать числа в диапазоне [−32767, +32767]. range;[3][4] Таким образом, это по крайней мере 16 бит (2 байта). На практике, во всех современных компиляторах имеет размер в 4 байта и диапазон [-2147483648, +2147483647]

long:

Тип длинного целого числа со знаком. Может содержать числа, как минимум, в диапазоне [−2 147 483 647, +2 147 483 647].[3][4] Таким образом, это по крайней мере 32 бита (4 байта).

Answer 1

Процессоры развивались постепенно все более расширяя емкость регистров. Например, ранее в DOS тип int соответствовал 16 разрядному целочисленному значению, так как на IBM-совместимых компьютеров регистры были 16-разрядными. Например, регистр AX является 16 разрядным, а его подрегистры AL и AH имели разрядность равную 8 битам. До этого вообще регистры процессоров были 8 разрядными.

Если выполнить, допустим, умножение двух объектов 16-разрядного типа int, то для хранения результата нужно использовать два регистра как, например, регистры AX и DX. Для этого результата уже нужно вводить новый целочисленный тип. И такой тип был введен. Это тип long .

Затем появились 64-разрядные процессоры. Необходимо различать 16-разрядные целые числа, 32-разрядные целые числа и 64- разрядные целые числа. Поэтому был введен дополнительный целый тип Long long. Имейте в виду, что нужно было сохранять обратную совместимость с целыми типами, введенными ранее для процессоров с меньшей разрядностью.

Поэтому в стандарте C принято, что

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

У разработчиков компиляторов есть свобода выбора, какая разрядность будет у типа long и других целочисленных типов. Например, разрядность типа long может составлять не `32 бита, а 64 бита.

Чтобы программы были переносимы, возникла необходимость вводить новые типы со строго указанной разрядностью такие, как, например, int_least32_t или int32_t.

На одних 64-битовых платформах тип long и тип long long могут иметь 64-битовуж разрядность. На других 64-битовых платформах тип long может быть 32-битовым и тип int также может быть 32-битовым, а тип long long - 64 битовым.

Тем не менее ранг типа long long больше ранга типа long, а тип long в свою очередь имеет ранг выше, чем тип int.

На этом основываются правила преобразования типов в выражениях. Например, если тип long и тип int имеют разрядность равную 32 битам, то в следующем фрагменте кода

long x = 0;
unsigned int y = 0;
x + y;

тип выражения x + y имеет тип unsigned long.

В связи с этим имеются некоторые курьезы, связанные с такими преобразованиями особенно при выборе перегруженной функции в C++.

Один из таких примеров описан в следующей теме, где ближе к ее концу (можно быстро найти это сообщение по ключевому слову int64_t) описывается один из таких курьезов, связанных с вызовом перегруженной функции, у которой параметр имеет тип std::int64_t, который, как оказалось, является не алиасом типа long long int, а алиасом типа long int, который на данной платформе является 64-битовым.

Answer 2

Размеры типов int и long не регламентированы Стандартом языка. Но регламентировано отношение их размеров, т.е. sizeof(int) <= sizeof(long).

На текущий момент можно сказать, что размер long зависит как от разрядности процессора, так и от используемой ОС. Например, для Linux и MacOS он будет 8 байт для 64bit архитектур, и 4 байта для 32bit архитектур. В Windows размер будет 4 байта, независимо от разрядности архитектуры.

Например, в Стандарте С++ даже встречается такой пример:

static_assert(sizeof(long) >= 8, "64-bit code generation required for this library.");

Использовать разные типы можно, например, для обеспечения перегрузки функций:

void f(int) {}
void f(long) {}
f(42); // int
f(42L); // long

Также не стоит забывать, что данные типы имеют разный ранг (integer conversion rank), что влияет на правила преобразования целочисленных типов.

Answer 3

Тип long не "занимает в памяти 4 байта". Он занимает как минимум 32 бита, т.е. имеет диапазон как минимум [−2147483647, +2147483647]. А сверху его размер не ограничен.

Тип int занимает как минимум 16 бит, ибо имеет диапазон как минимум [−32767, +32767] (как вы сами заметили).

Поэтом не совсем ясно, откуда вы взяли предположение об одинаковости диапазонов этих типов - уже из процитированного вами видно, что они запросто могут быть разными.

В языке С++ система целочисленных типов обладает тем свойством, что

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

т.е. вполне возможно что размеры (и диапазоны) этих типов все будут различными.

В языке С, по каким-то историческим причинам, это соотношение определяется как

диапазон(signed char) ⊆ диапазон(short) ⊆ диапазон(int) ⊆ диапазон(long) ⊆ диапазон(long long)

Но идея, понятное дело, в обоих случаях одна и та же. И все эти типы могут быть различными с точки зрения диапазона. Как, впрочем, все они могу быть и одинаковыми с точки зрения размера и диапазона.

То, что у вас на какой то платформе тип long совпал по представлению с типом int является лишь особенностью вашей платформы.

Answer 4

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

Когда тип используются часто, то компилятор оптимизирует работу с ним. После оптимизации в компиляторе, начинают рекомендовать использование типа для каких-то целей.

На разных архитектурах ЭВМ разные размеры регистров процессора, но соотношение размеров типов сохраняется.

Простыми словами: часто использовали int в программах, поэтому его вытянули под размер 4 байта на PC, что соответствует регистру процессора x32. long не стали вытягивать до 8 байт, потому что на x32 потребуется две команды процессору вместо одной. Но не удалять же long, ведь его используют какие-то программы.

READ ALSO
Можете объяснить суть этого pl/sql кода?

Можете объяснить суть этого pl/sql кода?

В этом PL/SQL коде есть вот такой код: l_balance:=account_balance(account_id_in)Вот эту строку кода не могу понять

359
Перевести Spring Security XML Config в java класс

Перевести Spring Security XML Config в java класс

Добрый деньУ меня есть конфигурация XML для Spring Security

593
СheckBox menu Java

СheckBox menu Java

Здравствуйте)Пишу мобильное приложение android

434
Как обработать исключение?

Как обработать исключение?

Есть try { //в этом блоке мы пишем код, где может возникнуть ошибка }

422