Сколько памяти занимает int

Обновлено: 07.07.2024

Я проверил общее пространство кучи, используя «Runtime.getRuntime (). totalMemory ()» и «maxMemory ()», и увидел, что я начинаю с 64 МБ, а максимальный - 900+ МБ, а во время запуска я получаю 900+ на кучу и раздавить.

Теперь я знаю, что Integer занимает 4 байта, поэтому, даже если я умножу 30 * 4 * 1000000, я все равно должен получить только 150-100 мегабайт.

Если я попробую с примитивным типом, например int, он сработает.

Примитив Java int займет 4 байта, но если вы используете ValueObject, например Integer, он займет гораздо больше места. В зависимости от вашей машины одна ссылка может занимать 32 или 64 бита + размер обертываемого примитива.

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

Это не то, что вы ищете, но оптимальным решением является использование функции вместо массива в этом простом примере.

Если у вас есть более реалистичный пример, вы можете использовать другие оптимизации.

Возможно, вам следует использовать базу данных, а не огромный массив, но если вы должны использовать огромный массив объектов, пробовали ли вы увеличить размер памяти Java с помощью аргумента командной строки -Xms при запуске средства запуска приложений Java?

Integer - объект, занимающий более 4 байтов. Насколько больше зависит от реализации. Вам действительно нужен Integer ? Единственное преимущество в том, что это может быть null . Возможно, вы могли бы вместо этого использовать «сигнальное значение»; скажем, -1 или Integer.MIN_VALUE .

Предположим, что мы говорим о недавней 32-битной JVM Sun.

  • Каждый объект типа Integer имеет 1 поле int , занимающее 4 байта.
  • Каждый объект типа Integer имеет 2 слова заголовка, занимающие 8 байтов.
  • Гранулярность распределения составляет (я считаю) 2 слова - 4 байта заполнения.
  • Integer [] имеет 1 ссылку для каждого элемента / позиции массива - 4 байта.

Таким образом, всего 20 байт на элемент массива. 20 x 30 x 1000000 = 600000000 Мбайт. Теперь добавьте тот факт, что сборщик поколений будет выделять не менее 3 пространств объектов разного размера, что может легко добавить до 900+ мегабайт.

  • Используйте int[] вместо Integer .
  • Если значения Integer в основном представляют собой числа в диапазоне от -128 до + 127, выделите их с помощью Integer.valueOf(int) . JLS гарантирует, что объекты Integer , созданные таким образом, будут совместно использоваться. (Обратите внимание, что когда Integer создается с помощью автоматической упаковки, тогда JLS предусматривает использование valueOf . Фактически, это «исправление» уже было применено в вашем примере.)
  • Если ваши значения Integer в основном поступают из более крупного, но все же небольшого домена, рассмотрите возможность реализации собственного кеша для совместного использования объектов Integer .

Мой вопрос был о Integer в качестве примера, в моей программе я использую свой собственный объект, который содержит только массив байтов (максимальный размер 4). когда я его создаю, он занимает в памяти намного больше 4 байтов.

Предположим, ваш класс определен следующим образом:

Каждый MyInt займет:

  • Слова заголовка MyInt - 8 байт
  • Поле MyInt.bytes - 4 байта
  • Заполнение - 4 байта
  • Заголовочные слова для байтового массива - 12 байт
  • Содержимое массива - 4 байта

Теперь добавьте место, занятое ссылкой MyInt :

Всего - 36 байтов на элемент MyInt в MyInt[] .

Сравните это с 20 байтами на элемент Integer в Integer[] или 4 байтами на элемент int в int[] .

Запутался.
Win7x64, консоль, MinGW.
1. Почему адресация по 4 байта?
Ведь это выглядит как 32-ух разрядная система, хотя установлена х64.
2. Почему int занимает 4 ячейки (то есть 16 байт), а не 1 ячейку (то есть 4 байта) ?
Если так и есть, и минимальная ячейка памяти равна 4 байтам, то понятно, почему char-у приходится занимать 4 байта, а не 1 байт.


Распутался:
Не нужно путать логическую адресацию и размер ячейки памяти. Ячейка памяти здесь - 8 бит или 1 байт.
Адресация здесь осуществляется с помощью 32-ух бит, то есть от 00 00 00 00 до FF FF FF FF.

15432

1. Чтоб узнать адресацию, напечатайте sizeof(void*) или любого другого указателя. Может оказаться, что программа действительно скомпилирована в х86
2. Все норм у вас, 4 байта на int, 1 байт на char. Каждая "ячейка" в 1 байт, а не в 4

Qubc

массив int
0 0028FF2C - первый член
0028FF2D
0028FF2E
0028FF2F
1 0028FF30 - второй член

То есть первый член в массиве int занимает 4 ячейки памяти, каждая ячейка по байту.

Qubc

Ячейки эв нашем случае 1 Байт.
Все ниже - верно?

Сколько можно адресовать таких ячеек 4 битами?
0000 Ячейка номер 0
0001 Ячейка номер 1
1111 Ячейка номер F
Итого - 2^4=16 однобайтных ячеек.
То есть 16 * 1 Байт = 16 Байт памяти.

Сколько ячеек 8 битами?
0000 0000 Ячейка 00
0000 0001 Ячейка 01
1111 1111 Ячейка FF
Итого - 2^8=256 однобайтных ячеек.
То есть 256 * 1 Байт = 256 Байт памяти.

Сколько ячеек 16 битами (или же 2 байтами)?
0000 0000 0000 0000 Ячейка 00 00
0000 0000 0000 0001 Ячейка 00 01
1111 1111 1111 1111 Ячейка FF FF
Итого - 2^16=65536 однобайтных ячеек.
То есть 65536 * 1 Байт = 65536 Байт = 65536 / 1024 = 64 килоБайт памяти.

Сколько ячеек 32 битами (или же 4 байтами)?
0000 0000 0000 0000 0000 0000 0000 0000 Ячейка 00 00 00 00
0000 0000 0000 0000 0000 0000 0000 0001 Ячейка 00 00 00 01
1111 1111 1111 1111 1111 1111 1111 1111 Ячейка FF FF FF FF
Итого - 2^32=4 294 967 296 однобайтных ячеек.
То есть 4 294 967 296 * 1 Байт = 4 294 967 296 Байт = 4 294 967 296 / 1024 = 4 194 304 килоБайт памяти.
4 194 304 / 1024 = 4096 мегаБайт = 4096 / 1024 = 4 гигабайта памяти.

Тем не менее, эта аналогия не совсем подходит к программированию, так как переменные могут занимать больше 1 байта памяти. Следовательно, одна переменная может использовать 2, 4 или даже 8 последовательных адресов. Объем памяти, который использует переменная, зависит от типа данных этой переменной. Так как мы, как правило, получаем доступ к памяти через имена переменных, а не через адреса памяти, то компилятор может скрывать от нас все детали работы с переменными разных размеров.

Есть несколько причин по которым полезно знать, сколько памяти занимает определенная переменная/тип данных.

Во-первых, чем больше она занимает, тем больше информации сможет хранить. Так как каждый бит содержит либо 0 , либо 1 , то 1 бит может иметь 2 возможных значения.

2 бита могут иметь 4 возможных значения:

бит 0 бит 1
0 0
0 1
1 0
1 1

3 бита могут иметь 8 возможных значений:

бит 0 бит 1 бит 2
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1

По сути, переменная с n-ным количеством бит может иметь 2 n возможных значений. Поскольку байт состоит из 8 бит, то он может иметь 2 8 (256) возможных значений.

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

Размер основных типов данных в C++

Язык C++ гарантирует только их минимальный размер:

Тип Минимальный размер
Логический тип данных bool 1 байт
Символьный тип данных char 1 байт
wchar_t 1 байт
char16_t 2 байта
char32_t 4 байта
Целочисленный тип данных short 2 байта
int 2 байта
long 4 байта
long long 8 байт
Тип данных с плавающей запятой float 4 байта
double 8 байт
long double 8 байт

Фактический размер переменных может отличаться на разных компьютерах, поэтому для его определения используют оператор sizeof.

Оператор sizeof — это унарный оператор, который вычисляет и возвращает размер определенной переменной или определенного типа данных в байтах. Вы можете скомпилировать и запустить следующую программу, чтобы выяснить, сколько занимают разные типы данных на вашем компьютере:

Я в последнее время немного затупил, не мог вспомнить, сколько байт занимает тип double в AVR-GCC. Обычно при программировании контроллеров работаешь с целочисленными типами, типа int и char, а к типам с плавающей точкой прибегаешь не часто, в связи с их ресурсоемкостью.

Поэтому, на будущее, оставлю себе здесь памятку с указанием размеров занимаемой памяти типами данных для компилятора AVR-GCC и диапазон изменения переменных этого типа.

Типы данных в языке Си для компилятора AVR-GCC

Тип Размер в
байтах (битах)
Интервал изменения
char 1 (8) -128 .. 127
unsigned char 1 (8) 0 .. 255
signed char 1 (8) -128 .. 127
int 2 (16) -32768 .. 32767
unsigned int 2 (16) 0 .. 65535
signed int 2 (16) -32768 .. 32767
short int 2 (16) -32768 .. 32767
unsigned short int 2 (16) 0 .. 65535
signed short int 2 (16) -32768 .. 32767
long int 4 (32) -2147483648 .. 2147483647
unsigned long int 4 (32) 0 .. 4294967295
signed long int 4 (32) -2147483648 .. 2147483647
float 4 (32) 3.4Е-38 .. 3.4Е+38
double 4 (32) 3.4Е-38 .. 3.4Е+38
long double 10 (80) 3.4Е-4932 .. 3.4Е+4932

В дополнение к этому, в библиотеках AVR-GCC введено несколько производных от стандартных типов. Они описаны в файле stdint.h. Сделано это, наверно, для улучшения наглядности и уменьшения текста программ (ускорения их написания :)). Вот табличка соответствия:

Производные типы от стандартных в языке Си для компилятора AVR-GCC

Производный тип Стандартный тип
int8_t signed char
uint8_t unsigned char
int16_t signed int
uint16_t unsigned int
int32_t signed long int
uint32_t unsigned long int
int64_t signed long long int
uint64_t unsigned long long int

Тип Void

Логический тип, может принимать только 2 значения - true (правда) и false (ложь). В памяти занимает 1 байт.

Тип позволяет хранить 1 алфавитно-цифровой символ и занимае 1 байт. Для записи символа используются одинарные кавычки.

В памяти хранится число, соответствующее записанному символу в таблице ASCII, поэтому над переменной можно производить арифметические действия.

Переменная это типа - знаковая, диапазон допустимых значений - от -128 до 127.

Тип для хранения однобайтового целого беззнакового числа. Соответственно диапазон значений от 0 до 255.

Пожалуй самый частоиспользуемый тип для хранения целых чисел со знаком - integer (целое число). Занимает 2 байта и может хранить цисла от -32768 до 32767.

На платформе Arduino также присутствует тип , который ничем не отличается от типа int .

unsigned int

Беззнаковое целое число, занимает так же, как и int , 2 байта. Диапазон значений - от 0 до 65535.

Тип long служит для хранение больших целых знаковых чисел. Диапазон его значений от -2147483648 до 2147483647, а занимает в памяти он 4 байта.

unsigned long

Беззнаковое целое число расширенного диапазона может хранить значения от 0 до 4294967295 и занимает 4 байта.

float

Тип данных чисел с плавающей точкой (или с плавающей запятой). Используется для нецелочисленных расчетов. В Arduino используется например для считывания значений с аналоговых пинов. Диапазон значений от -3.4028235E+38 до 3.4028235E+38,а занимает такая переменная 4 байта.

Точность - 6-7 знаков после запятой.

double

Тип ничем не отличается от типа float и введен для обратной совместимости. На многих других платформах он имеет большую чем у float точность.

string

Тип для хранение текстовых строк. Является массивом символов типа char и символа конца строки '\0' в последнем его элементе. Не путать с классами string и String .

Строка может быть создана и инициализирована несколькими способами:

Если забыть указать символ конца строки при посимвольной инициализации или не отвести под него место, то функции работы со строками будут работать некорректно.

массив

Массив - это набор элементов одного типа с доступом к каждому элементу по индексу.

Нумерация индексов массива начинается с 0.

Ключевое слово void используется при объявлении функции, которая не возвращает значения.

Преобразование типов

Преобразование типов - это приведение значение переменной к другому типа, отличному от типа данной переменной.

Приведение типов делится на явное и неявное.

Пример явного приведения типа:

Пример неявного приведения типа:

Условная конструкция if принимает на вход значение типа boolean , поэтому целочисленное значение переменной a будет приведено к типа boolean .

Читайте также: