Почему вы не можете хранить очень большое одиночное значение в динамически выделенном блоке памяти? - PullRequest
4 голосов
/ 18 февраля 2020

Почему я не могу сохранить большое целое число в этом выделенном блоке памяти?

int *dyn = malloc(16);
*dyn = 9999999999;

printf("%lli\n", *dyn);

free(dyn);

Во время компиляции G CC предупреждает меня о переполнении целого числа. И, конечно же, при распечатке он переполнен.

Почему я не могу использовать весь блок памяти для хранения одного значения?

Ответы [ 5 ]

6 голосов
/ 18 февраля 2020

*dyn = 9999999999; не предписывает компьютеру использовать всю память, выделенную для dyn, для хранения значения 9999999999.

В C, dyn имеет тип. Тип «указатель на int». Тогда *dyn имеет тип int, который имеет специфику c, фиксированное число битов. У него нет типа, означающего «вся память, выделенная для dyn».

Поскольку *dyn - это int, *dyn = 9999999999; говорит компьютеру поместить 9999999999 в int , Поскольку 9999999999 слишком велик для int в вашей реализации C, возникает переполнение.

Мы можем программировать компьютеры и разрабатывать языки программирования для управления целыми числами произвольных размеров. Некоторые языки, такие как Python, делают это. Однако для этого требуется дополнительное программное обеспечение, в частности, программное обеспечение, которое должно выполнять некоторую переменную работу во время работы программы, чтобы обрабатывать любые размеры чисел. C предназначен для элементарного языка. Он работает с объектами определенного размера c и обычно переводит код C в фиксированные объемы работы в инструкциях процессора. Они обеспечивают строительные блоки для программистов для создания большего программного обеспечения. Так, в C, int объекты имеют фиксированные размеры. Выделение 16 байт памяти обеспечивает пространство для нескольких int объектов, но не предоставляет большого целочисленного объекта.

5 голосов
/ 18 февраля 2020

Размер int обычно составляет 4 байта (32 бита). И это может занять 2 ^ 32 различных состояния от -2147483648 до 2147483647. Поэтому, когда вы пытаетесь сохранить это *dyn = 9999999999;, происходит целочисленное переполнение. Он не указывает на область памяти, он указывает на значение этой переменной.

1 голос
/ 18 февраля 2020

Почему я не могу использовать весь блок памяти для хранения одного значения?

Поскольку размер int почти наверняка не равен 16 байтам, а когда вы -отправьте указатель int в выражении *dyn = 9999999999;, что доступ ограничен размером int, который, вероятно, составляет 2 ^ 31 - 1.

Обратите внимание, что целочисленная константа 9999999999 также имеет тип, который динамически определяется компилятором в зависимости от размера числа. В этом случае очень вероятно long long. Таким образом, настоящая ошибка здесь - ваша попытка сделать int x = 9999999999;, которая не имеет ни малейшего отношения к mallo c или указателям. Это простое переполнение.

Чтобы использовать числа больше 2,14 миллиарда, вы должны вместо этого использовать 64-битный тип. Используйте int64_t / uint64_t из stdint.h.

Вы не можете выделить 16 байтов, значение memcpy сом и затем получить доступ к данным через указатели на некоторый произвольный целочисленный тип. Это из-за несколько дисфункциональной системы типа C. Упрощенное объяснение: кусок данных, возвращаемых из mallo c, не имеет внутреннего типа, пока вы не сохраните что-то там. Затем он получает тип, который вы использовали при хранении, и все последующие обращения должны использовать этот же тип, все остальное вызывает неопределенное поведение в соответствии с «правилом строгого алиасинга».

0 голосов
/ 18 февраля 2020

9999999999 или лучше, если 9,999,999,999 не находится в диапазоне int, на который указывает dyn, не имеет значения, сколько памяти выделено malloc:

int *dyn = malloc(16);   // `dyn` points to an `int` object, don´t matter 
                         // if malloc allocates 16 bytes.
*dyn = 9999999999;       // Attempt to assign an out-of-range value to an `int` object.

Объект типа int должен выделяться 4 байтами в памяти самыми современными системами.

4 байта могут содержать максимум 2 ^ (8 * 4) = 2 ^ 32 = 4 294 967 296 значений.

Теперь у вас есть тип int, который эквивалентен типу signed int.

signed int может хранить положительные и отрицательные числа, но так как он может хранить положительные и отрицательные числа Числа у него совсем другой диапазон.

signed int имеет диапазон от -2 147 483 648 до 2 147 483 647, а также диапазон int.

Таким образом, вы не можете удерживать 9 999 999 999 в int объект, поскольку максимальное значение, которое может хранить объект int, равно 2 147 483 647.

Если вы хотите сохранить значение 9 999 999 999 или 9999999999 в объекте, используйте fe long long int, но не long int, поскольку long int может содержать одинаковый диапазон int и unsigned int:

long long int *dyn = malloc(16);   // `dyn` points to an `long long int` object.
*dyn = 9999999999;  // Fine, because 9999999999 is in the range of an `long long int` object.
0 голосов
/ 18 февраля 2020

dyn - целочисленный указатель (фактически, указывающий на зарезервированную память массива int из 16 байтов). *dyn - целое число (первый элемент из этого массива int). Как и в случае массивов:

int dyn[4];
dyn[0]=9999999999;

Назначение 9999999999 для int приводит к переполнению переменной, поскольку int допускает только на современных платформах [−2 147 483 648, +2 147 483 647] диапазон (и не менее [−32767, +32767]).

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