Размер C «int» 2 байта или 4 байта?

169

Переменная Integer в C занимает 2 байта или 4 байта? От каких факторов это зависит?

В большинстве учебников говорится, что целочисленные переменные занимают 2 байта. Но когда я запускаю программу, печатающую последовательные адреса массива целых чисел, это показывает разницу 4.

Раджив Пратхап
источник
6
en.wikipedia.org/wiki/…
Эван Мулавски
1
intэто просто один из нескольких целочисленных типов. Вы спрашивали о размере "целое число"; Вы, вероятно, хотели спросить о размере int.
Кит Томпсон
3
И вы должны найти лучшие учебники. Учебник, который говорит, что intявляется 2 байтами (а), вероятно, относится к старой системе, и (б) не дает понять, что размер будет варьироваться от одной системы к другой. Лучшая книга по Си - «Язык программирования Си» Кернигана и Ричи, хотя он предполагает некоторый опыт программирования. См. Также вопрос 18.10 в comp.lang.c FAQ .
Кит Томпсон
2
Попробуйте #define int int64_tна 64-битной платформе, так что ни того, ни другого. Просто используйте sizeof. ;-)
netcoder

Ответы:

183

Я знаю , что это равно sizeof(int). Размер intдействительно зависит от компилятора. В те времена, когда процессоры были 16-битными, intбыло 2 байта. В настоящее время это чаще всего 4 байта в 32-разрядных и 64-разрядных системах.

Тем не менее, использование sizeof(int)- лучший способ получить размер целого числа для конкретной системы, на которой выполняется программа.

РЕДАКТИРОВАТЬ: Исправлено неправильное выражение, которое intсоставляет 8 байт в большинстве 64-разрядных систем. Например, это 4 байта на 64-битном GCC.

yhyrcanus
источник
31
@RajivPrathap: Ну, это зависит от компилятора, но компилятор решает, является ли он также машинно-зависимым. :)
user541686
2
Если вам нужен размер препроцессора, вы можете проверить предопределенные макросы, такие как INT_MAX. Если значение не соответствует ожидаемому в вашем коде, тогда размер байта int отличается в текущей комбинации компилятор / платформа.
Уолт Селлерс
3
Это зависит не только от машины, но и от операционной системы, работающей на машине. Например, long в Win64 составляет 4 байта, тогда как long в Linux64 составляет 8 байтов.
Джем Калионку
9
неправильно. в большинстве 64-битных систем int по-прежнему составляет 4 байта en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models
phuclv
7
sizeof(int)может быть любым значением от 1. Байт не обязательно должен быть 8 битами, а некоторые машины не имеют 8-битной адресуемой единицы (что в основном является определением байта в стандарте). Ответ не верен без дополнительной информации.
слишком честно для этого сайта
103

Это одна из точек в C, которая может сначала сбить с толку, но стандарт C определяет только минимальный диапазон для целочисленных типов, который гарантированно поддерживается. intгарантированно может содержать от -32767 до 32767, что требует 16 бит. В этом случае int, это 2 байта. Однако реализации могут выйти за пределы этого минимума, как вы увидите, что многие современные компиляторы делают int32-битные (что также означает, что 4 байта довольно повсеместно).

Причина, по которой ваша книга говорит о 2 байтах, скорее всего потому, что она старая. Когда-то это было нормой. В общем, вы всегда должны использовать sizeofоператор, если вам нужно выяснить, сколько байтов на платформе вы используете.

Чтобы решить эту проблему, C99 добавил новые типы, где вы можете явно запросить целое число определенного размера, например int16_tили int32_t. До этого не было универсального способа получить целое число определенной ширины (хотя большинство платформ предоставляло похожие типы для каждой платформы).

Фатальная ошибка
источник
7
@nevanking: На двухкомпьютерной машине (каждая машина, о которой я знаю ...), да. Но C не гарантирует, что это так.
FatalError
@nevanking Я совершенно новичок в C, но разве это не 32767, потому что в противном случае он использовал бы еще один бит | байт? Представьте себе, я могу держать 3 цифры (0 или 1), поэтому я могу перейти от 000 до 111 (что является десятичным 7). 7 прямо перед показателем 2. Если бы я мог идти до 8 (1000), то я мог бы использовать эти 4 цифры вплоть до 15! Например, 32767 находится прямо перед показателем степени 2, исчерпывая все доступные биты | байты.
RGS
3
@RSerrao Я тоже не эксперт C, но AFAIK для положительных чисел на единицу меньше максимального отрицательного числа. Итак, от -8 до 7, от -256 до 255 и так далее. Отрицательные числа не должны считать ноль.
Неванский король
1
«16 бит. В этом случае int, это 2 байта» может быть неправильным, если CHAR_BIT равен 16, sizeof (int) может быть 1 байт (или символ).
12431234123412341234123
6
@nevanking: только если вы предполагаете, что дополнение 2 будет подписано int. С не делает этого предположения. Системы дополнения и величины знака 1 не могут быть представлены -32768в 16 битах; скорее, они имеют два представления для нуля (положительное и отрицательное). Поэтому минимальный диапазон для intэто [-32767..32767].
Джон Боде
33

Там нет конкретного ответа. Это зависит от платформы. Это определяется реализацией. Это может быть 2, 4 или что-то еще.

Идея intзаключалась в том, что он должен был соответствовать естественному размеру «слова» на данной платформе: 16-битная на 16-битных платформах, 32-битная на 32-битных платформах, 64-битная на 64-битных платформах. Однако в целях обратной совместимости некоторые компиляторы предпочитают придерживаться 32-разрядных intдаже на 64-разрядных платформах.

Время 2-х байт intуже давно прошло (16-битные платформы?), Если только вы не используете какую-то встроенную платформу с 16-битным размером слова. Ваши учебники, вероятно, очень старые.

Муравей
источник
2
The idea behind int was that it was supposed to match the natural "word" size on the given platform- Это то, что я искал. Есть идеи, в чем причина? В свободном мире int может занимать любое количество последовательных байтов в памяти, верно? 8, 16, что угодно
bholagabbar
19

Ответ на этот вопрос зависит от того, какую платформу вы используете.
Но независимо от платформы вы можете надежно предположить следующие типы:

 [8-bit] signed char: -127 to 127
 [8-bit] unsigned char: 0 to 255
 [16-bit]signed short: -32767 to 32767
 [16-bit]unsigned short: 0 to 65535
 [32-bit]signed long: -2147483647 to 2147483647
 [32-bit]unsigned long: 0 to 4294967295
 [64-bit]signed long long: -9223372036854775807 to 9223372036854775807
 [64-bit]unsigned long long: 0 to 18446744073709551615
Приянк Арора
источник
3
Кто-то отредактировал ваше сообщение, чтобы «исправить» диапазоны, но я не уверен, что ваше редактирование адекватно отражает ваши намерения. Он предполагает реализацию в два дополнения, что будет справедливо в большинстве случаев, но не во всех. Поскольку ваш ответ конкретно указывает на зависимость от реализации, я думаю, что редактирование, вероятно, неправильно. Если вы согласны, пожалуйста, не забудьте отредактировать изменения.
Коди Грей
1
@ k06a Ваше редактирование было неверным . Вы специально изменили исходные диапазоны на диапазоны с двумя дополнениями - это не те, которые указаны в стандарте C.
Антти Хаапала
@CodyGray это колебалось взад и вперед, будучи совместимым с дополнением 1 в течение последних 3 лет, и OP ничего не сказал, поэтому я отменил редактирование, которое изменило его на дополнение 2 с «фиксированными диапазонами», так как оно говорит: «Вы можете надежно предположить» , что до сих пор не совсем верно.
Антти Хаапала
13

Переменная Integer в C занимает 2 байта или 4 байта?

Это зависит от платформы, которую вы используете, а также от конфигурации вашего компилятора. Единственный надежный ответ - использовать sizeofоператор, чтобы увидеть, насколько велико целое число в вашей конкретной ситуации.


От каких факторов это зависит?

Лучше всего рассмотреть диапазон , а не размер . И то, и другое будет отличаться на практике, хотя гораздо более надежно выбирать типы переменных по диапазону, чем по размеру, как мы увидим. Также важно отметить, что стандарт побуждает нас рассмотреть возможность выбора целочисленных типов на основе диапазона, а не размера , но сейчас давайте проигнорируем стандартную практику и позволим нашему любопытству исследовать sizeofбайты CHAR_BITи целочисленное представление ... кроличью нору и сами все увидим ...


sizeof, байтов и CHAR_BIT

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

sizeofОператор дает размер (в байтах) своего операнда, который может быть выражение в скобках или имя типа. Размер определяется по типу операнда.

При условии четкого понимания мы приведем к обсуждению байтов . Обычно предполагается, что байт составляет восемь битов, когда фактически CHAR_BITговорит вам, сколько битов в байте . Это просто еще один из тех нюансов, который не учитывается при разговоре об общих двух (или четырех) байтовых целых числах .

Давайте подведем итоги:

  • sizeof => размер в байтах и
  • CHAR_BIT => количество бит в байте

Таким образом, в зависимости от вашей системы, sizeof (unsigned int)может быть любое значение больше нуля (а не только 2 или 4), как если бы CHAR_BITэто было 16, то один (шестнадцатиразрядный) байт содержит достаточно битов, чтобы представить шестнадцатибитовое целое число, описываемое стандарты (цитируется ниже). Это не обязательно полезная информация, не так ли? Давайте углубляться глубже ...


Целочисленное представление

В C стандарт устанавливает минимальные точности / дальность для всех стандартных целочисленных типов (и CHAR_BIT, тоже, FWIW) здесь . Из этого мы можем получить минимум для того, сколько бит требуется для хранения значения , но мы можем также просто выбрать наши переменные на основе диапазонов . Тем не менее, огромная часть деталей, необходимых для этого ответа, находится здесь. Например, следующее, что стандарт unsigned intтребует (по крайней мере) шестнадцать бит хранения:

UINT_MAX                                65535 // 2¹⁶ - 1

Таким образом, мы можем видеть, что unsigned intтребуется ( как минимум ) 16 битов , и именно здесь вы получаете два байта (предполагая, что CHAR_BITэто 8) ... и позже, когда этот предел увеличился до 2³² - 1, люди указали вместо этого 4 байта. Это объясняет явления, которые вы наблюдали:

В большинстве учебников говорится, что целочисленные переменные занимают 2 байта. Но когда я запускаю программу, печатающую последовательные адреса массива целых чисел, это показывает разницу 4.

Вы используете древний учебник и компилятор, который учит вас непереносимым Си; автор, написавший ваш учебник, может даже не знать об этом CHAR_BIT. Вы должны обновить свой учебник (и компилятор) и стремиться помнить, что информационные технологии - это постоянно развивающаяся область, в которой вам нужно быть впереди, чтобы конкурировать ... Впрочем, хватит об этом; давайте посмотрим, какие еще непереносимые секреты хранятся в этих целочисленных байтах ...

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

Подписывать биты ... В приведенном выше примере я указал UINT_MAXверхний предел, unsigned intпотому что это тривиальный пример извлечения значения 16из комментария. Для типов со знаком, чтобы различать положительные и отрицательные значения (это знак), мы также должны включить бит знака.

INT_MIN                                -32768 // -(2¹⁵)
INT_MAX                                +32767 // 2¹⁵ - 1

Биты заполнения ... Хотя встречаться с компьютерами, у которых биты заполнения являются целыми числами, нечасто, стандарт C допускает это; некоторые машины (т.е. этот ) реализуют большие целочисленные типы, комбинируя два меньших (знаковых) целочисленных значения вместе ... и когда вы объединяете целые числа со знаком, вы получаете потерянный знаковый бит. Этот потерянный бит считается заполнением в C. Другие примеры битов заполнения могут включать биты четности и биты прерывания .


Как вы можете видеть, стандарт, кажется, поощряет учитывать диапазоны, такие как INT_MIN... INT_MAXи другие минимальные / максимальные значения из стандарта, при выборе целочисленных типов, и не рекомендует полагаться на размеры, так как есть другие тонкие факторы, которые могут быть забыты, такие как CHAR_BITбиты заполнения, которые может повлиять на значение sizeof (int)(то есть распространенные заблуждения о двухбайтовых и четырехбайтовых целых числах игнорируют эти детали).

Flimzy
источник
13

C99 N1256 стандартная тяга

http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf

Размер intи все другие целочисленные типы определяются реализацией, C99 определяет только:

  • минимальный размер гарантии
  • относительные размеры между типами

5.2.4.2.1 «Размеры целочисленных типов <limits.h>» дает минимальные размеры:

1 [...] их значения, определенные реализацией, должны быть равны или больше по величине (абсолютное значение) показанным [...]

  • UCHAR_MAX 255 // 2 8 - 1
  • USHRT_MAX 65535 // 2 16 - 1
  • UINT_MAX 65535 // 2 16 - 1
  • ULONG_MAX 4294967295 // 2 32 - 1
  • ULLONG_MAX 18446744073709551615 // 2 64 - 1

6.2.5 «Типы» затем говорит:

8 Для любых двух целочисленных типов с одинаковыми знаками и разным целочисленным рангом преобразования (см. 6.3.1.1) диапазон значений типа с меньшим целочисленным рангом преобразования является поддиапазоном значений другого типа.

и 6.3.1.1 «Булевы, символы и целые числа» определяют относительные ранги преобразования:

1 Каждый целочисленный тип имеет ранг целочисленного преобразования, определенный следующим образом:

  • Ранг long long int должен быть больше ранга long int, который должен быть больше, чем ранг int, который должен быть больше, чем ранг short int, который должен быть больше, чем ранг подписанного символа char.
  • Ранг любого целого типа без знака должен равняться рангу соответствующего целого типа со знаком, если таковой имеется.
  • Для всех целочисленных типов T1, T2 и T3, если T1 имеет больший ранг, чем T2, и T2 имеет больший ранг, чем T3, то T1 имеет больший ранг, чем T3
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
источник
8

Единственные гарантии , что charдолжно быть по крайней мере , 8 битов в ширину, shortи intдолжны быть по крайней мере , 16 бит, и longдолжно быть по крайней мере , 32 бита, а также, что sizeof (char)<= sizeof (short)<= sizeof (int)<= sizeof (long)( То же самое справедливо и для беззнаковых версий этих типов ).

int может иметь ширину от 16 до 64 бит в зависимости от платформы.

Джон Боде
источник
6

Размер C «int» 2 байта или 4 байта?

Ответ «да» / «нет» / «возможно» / «возможно нет».

Язык программирования C определяет следующее: наименьшая адресуемая единица, известная charи называемая также «байтом» , имеет CHAR_BITширину ровно в битах, где CHAR_BITне менее 8.

Таким образом, один байт в C не обязательно является октетом , то есть 8 битами. В прошлом одна из первых платформ для запуска кода на C (и Unix) имела 4 байта, intно в общей сложности intимела 36 бит, потому что CHAR_BITбыла 9!

intПредполагается, что это натуральный целочисленный размер для платформы, которая имеет диапазон не менее-32767 ... 32767 . Вы можете получить размер intв байтах платформы с помощью sizeof(int); когда вы умножите это значение, CHAR_BITвы узнаете, насколько оно шире в битах.


Хотя 36-битные машины в основном не работают, все еще существуют платформы с не 8-битными байтами. Буквально вчера возник вопрос о микроконтроллере Texas Instruments с 16-битными байтами , который имеет C99, C11-совместимый компилятор.

На TMS320C28x , кажется , что char, shortи intесть все 16 бит, и , следовательно , один байт. long int2 байта и long long int4 байта. Прелесть C в том, что можно написать эффективную программу для такой платформы и даже сделать ее переносимым способом!

Антти Хаапала
источник
"потому что CHAR_BIT было 9!" - Тогда у них было 362880 битных вычислений !? Впечатляет.
Джош Десмонд
5

В основном это зависит от платформы, которую вы используете. Это зависит от компилятора до компилятора. В настоящее время в большинстве компиляторов int составляет 4 байта . Если вы хотите проверить, что использует ваш компилятор, вы можете использовать sizeof(int).

main()
{
    printf("%d",sizeof(int));
    printf("%d",sizeof(short));
    printf("%d",sizeof(long));
}

Единственное, что обещает компилятор c, это то, что размер short должен быть равен или меньше, чем int, а размер long должен быть равен или больше, чем int. Так что, если размер int равен 4, то размер short может быть 2 или 4, но не больше. чем это. То же самое верно для долго и инт. Это также говорит о том, что размер короткого и длинного не может быть одинаковым.

justpraveen
источник
1
Использование %dдля size_tпараметра UB.
Пол Р
3

Это зависит от реализации, но обычно от x86 и других популярных архитектур, таких как ARM, intзанимает 4 байта. Вы всегда можете проверить во время компиляции, используя sizeof(int)любой другой тип, который вы хотите проверить.

Если вы хотите убедиться, что вы используете тип определенного размера, используйте типы в <stdint.h>

Слартибартфаст
источник
2
#include <stdio.h>

int main(void) {
    printf("size of int: %d", (int)sizeof(int));
    return 0;
}

Это возвращает 4, но это, вероятно, зависит от машины.

законы
источник
1

Размер C «int» 2 байта или 4 байта?

Переменная Integer в C занимает 2 байта или 4 байта?

C позволяет «байты» быть чем-то отличным от 8 бит на «байт».

CHAR_BIT количество бит для наименьшего объекта, который не является битовым полем (байтом) C11dr §5.2.4.2.1 1

Значение, превышающее 8, становится все более редким. Для максимальной переносимости используйте, CHAR_BITа не 8. Размер intв битах в C равен sizeof(int) * CHAR_BIT.

#include <limits.h>
printf("(int) Bit size %zu\n", sizeof(int) * CHAR_BIT);

От каких факторов это зависит?

Размер intбита обычно составляет 32 или 16 бит. C указанными минимальными диапазонами :

минимальное значение для объекта типа int INT_MIN-32767
максимальное значение для объекта типа int INT_MAX+32767
C11dr §5.2.4.2.1 1

Минимальный диапазон для intсил битого размера , чтобы быть по крайней мере , 16 - даже если процессор был «8-бит». Размер как 64 бита замечен в специализированных процессорах. Другие значения, такие как 18, 24, 36 и т. Д., Встречались на исторических платформах или, по крайней мере, теоретически возможны. Современное кодирование редко беспокоит intразмер не -2- битных битов.

Процессор и архитектура компьютера определяют intвыбор размера бит.

Тем не менее, даже с 64-разрядными процессорами intразмер компилятора может быть 32-разрядным из соображений совместимости, поскольку большие базы кода зависят от int32-разрядного (или 32/16).

Chux - Восстановить Монику
источник
-1

Это хороший источник для ответа на этот вопрос.

Но этот вопрос является своего рода всегда правдой и отвечает: «Да. Оба».

Это зависит от вашей архитектуры. Если вы собираетесь работать на 16-битной машине или меньше, она не может быть 4 байта (= 32 бит). Если вы работаете на 32-битной машине или лучше, ее длина 32-битная.

Чтобы выяснить, подготовьте ли вы программу для вывода чего-то читаемого и используйте функцию «sizeof». Это возвращает размер в байтах вашего объявленного типа данных. Но будьте осторожны, используя это с массивами.

Если вы объявляете, int t[12];он вернет 12 * 4 байта. Чтобы получить длину этого массива, просто используйте sizeof(t)/sizeof(t[0]). Если вы собираетесь создать функцию, которая должна рассчитывать размер отправляемого массива, помните, что если

typedef int array[12];
int function(array t){
    int size_of_t = sizeof(t)/sizeof(t[0]);
    return size_of_t;
}
void main(){
    array t = {1,1,1};  //remember: t= [1,1,1,0,...,0]
    int a = function(t);    //remember: sending t is just a pointer and equal to int* t
   print(a);   // output will be 1, since t will be interpreted as an int itselve. 
}

Так что это даже не вернет что-то другое. Если вы определили массив и попытаетесь впоследствии получить длину, используйте sizeof. Если вы отправляете массив в функцию, помните, что значение send это просто указатель на первый элемент. Но в первом случае вы всегда знаете, какой размер имеет ваш массив. Случай два можно выяснить, определив две функции и упустив некоторые характеристики. Определите функцию (массив t) и определите function2 (массив t, int size_of_t). Вызовите «function (t)», чтобы измерить длину некоторой копировальной работой и отправьте результат в function2, где вы можете делать что угодно с переменными размерами массива.

Shalec
источник
Предоставленная ссылка является плохим источником информации, потому что она предполагает вещи, которые не всегда являются правдой (например char, всегда signed)
Андрей Дамиан-Фекете