#c #integer #sizeof
#c #целое число #sizeof
Вопрос:
Если я сделаю
int a = 3, тогда 3 будет представлено в двоичном формате с 32 битами.
Если я сделаю
char a = 3, тогда 3 будет представлено в двоичном формате с 8 битами.
Мой вопрос заключается в том, прежде чем выполнять инициализацию значением, сколько битов представлено 3?
(Другими словами, сколько битов имеет «3» в правой части знака равенства)
Комментарии:
1. Вы не можете сказать наверняка. Вы можете только сказать, что это тип
signed int
, который может варьироваться в зависимости от вашей системы. Я бы рекомендовал вам#include <stdint.h>
иметь возможность определять размер и знак констант, например, используя макросUINT32_C(3)
для представления 3 в виде 32-разрядного int без знака.2. Я слышал о некоторых реализациях, имеющих
int
-s со 128 битами и 16 битchar
-s (эмулируемых). Проверьте, купив, а затем прочитав последний стандарт ISO C или, по крайней мере, n1570
Ответ №1:
Очень распространено, что int
имеет 32 бита, но это не гарантировано. Оно также может быть 16 или 64. Или выше.
Single — 3
это целочисленный литерал типа int
.
Ответ №2:
Вы можете проверить это с помощью sizeof
operator . Это даст вам размер аргумента в байтах. Просто попробуйте получить размер int
, a
и 3
.
#include <stdio.h>
int main()
{
int a = 3;
printf("%ldn", sizeof(a)); // gives 4 bytes (32 bit) on my PC
printf("%ldn", sizeof(int)); // gives 4 bytes (32 bit) on my PC
printf("%ldn", sizeof(3)); // gives 4 bytes (32 bit) on my PC
return 0;
}
Кроме того, 3
имеет тип int
. Таким образом, его размер равен размеру int
.
Ответ №3:
Размер объекта типа int
определяется реализацией, стандарт предъявляет только требование, которое INT_MAX
не должно быть меньше 32767
, чем это 2 ^ 15 - 1
Если в вашей системе размер объекта типа int
равен 4, то целочисленная константа like 3
будет занимать блок памяти, равный 4
байтам.
Обратите внимание на то, что, например, символьная целочисленная константа также имеет тип int
.
Итак, в обоих этих объявлениях
char a = 3;
и
char a = '3';
константы 3
и '3'
имеющие тип int
занимают 4
байты, если sizeof( int )
равно 4
.
Ответ №4:
Называется 3
целочисленной константой и имеет тип, очень похожий на любую именованную переменную. Это всегда тип, int
если введенное число может поместиться внутри int
. В противном случае, если оно не может поместиться, компилятор попытается поместить его в a long
, тогда long long
.
Существуют различные довольно сложные правила для того, как это делается, я не буду упоминать здесь все грязные детали — те, кто интересуется этим, могут проверить таблицы в стандарте C 6.4.4.1. Для среднего программиста, вероятно, достаточно знать, что мы также можем принудительно использовать целочисленную константу без знака с помощьюдобавление U
суффикса или принудительное long
добавление L
суффикса. Это 3U
или 3L
или комбинация 3UL
. (Нижний регистр u
и l
тоже работает.)
На реальных компьютерах int
всегда имеет размер 2 или 4 байта. long
имеет размер 4 или 8 байт. Пример с 64-разрядного компьютера Linux с 4 байтами int
и 8 байтами long
:
#include <stdio.h>
int main (void)
{
printf("%zun", sizeof(int)); // 4
printf("%zun", sizeof(3)); // 4
printf("%zun", sizeof(3L)); // 8
printf("%zun", sizeof(2147483647)); // 4, fits int
printf("%zun", sizeof(2147483648)); // 8, doesnt fit
}
Ответ №5:
Вопрос «сколько битов представлено 3?» на самом деле сложный. Если мы сможем найти 3, мы сможем ответить на него. Итак, вопрос: где 3?
Что на самом деле происходит, так это:
int a = 3;
это то же самое, что:
int a;
a = 3;
Компилятор гарантирует, что для переменной будет 4 байта a
свободного места (он делает это во время компиляции), а затем он также помещает в программу инструкцию, которая сохраняет число 3 в этом пространстве при запуске программы.
Мы можем использовать этот полезный онлайн-инструмент для компиляции программы и посмотреть, какой ассемблерный / машинный код фактически выводит компилятор: https://godbolt.org/z/a9Pohn
В этом случае я вошел в программу:
int main() {
int a;
a = 3;
}
и скомпилировал его с помощью «x86-64 gcc 10.2», без оптимизации. Вот скомпилированный код (как ассемблерный, так и машинный):
main:
55 push rbp
48 89 e5 mov rbp,rsp
c7 45 fc 03 00 00 00 mov DWORD PTR [rbp-0x4],0x3
b8 00 00 00 00 mov eax,0x0
5d pop rbp
c3 ret
Если мы сможем прочитать сборку, мы увидим, что инструкция, которую компилятор выбрал для вставки в программу для инициализации переменной a
, была mov DWORD PTR [rbp-0x4],0x3
. И в машинном коде это записано c7 45 fc 03 00 00 00
. Инструкция — это то, откуда берется число 3.
Длина инструкции составляет 7 байт. c7 45
сообщите процессору, что это за инструкция («поместите определенное число в определенную позицию в кадре стека»). fc
это позиция во фрейме стека. И 03 00 00 00
это конкретное число, которое оно туда помещает (в формате с малым порядковым номером). Это число 3 в исходном коде. Таким образом, в этом случае оно занимает 4 байта.
Обратите внимание, что это не всегда одно и то же. Если мы компилируем для процессора ARM вместо x86-64, то это соответствующие инструкции
mov r3, #3
str r3, [fp, #-8]
К сожалению, godbolt не показывает нам машинный код, но мы можем посмотреть инструкцию MOV # в руководстве ARM, в котором говорится, что длина инструкции составляет 4 байта, а перемещаемое число занимает всего 2 из этих байтов! Остальные биты автоматически обнуляются. Если вы используете число, которое не умещается в 2 байта, очевидно, что оно использует другую инструкцию.
Обычно мы не говорим о размерах инструкций, поскольку они различаются намного больше, чем размеры данных. int a;
всегда резервируется 4 байта (если в вашей системе int
4 байта), но инструкция, которая помещает определенные биты в это пространство, может иметь разные размеры.
Даже на x86-64 числа могут занимать разное количество места. Если я это сделаю return 0;
, компилятор преобразует это в xor eax, eax
( 31 c0
) . 0
В этой инструкции вообще нет числа! ( 31 c0
это все типы инструкций, без данных)