#include
#include
#include
main()
{
int i, aSize;
int * randomNums;
time_t t;
double total = 0;
int biggest, smallest;
float average;
srand(time(&t));
printf("Сколько случайных чисел будет в массиве? ");
scanf(" %d", &aSize);
randomNums = (int *) malloc(aSize * sizeof(int));
// Проверка правильности выделения массива
if (!randomNums)
{
printf("Ошибка выделения массива случайных
чисел! \n");
exit(1);
}
// Проход по элементам массива и присвоение
//каждому элементу
// целого числа в диапазоне от 1 до 500
for (i = 0; i < aSize; i++)
{
randomNums[i] = (rand() % 500) + 1;
}
// Инициализация самого большого и самого
// маленького числа для последующего сравнения
biggest = 0;
smallest = 500;
// Проход по заполненному массиву и поиск
// наибольшего и наименьшего чисел, а также
// сложение всех чисел и вычисление среднего
for (i = 0; i < aSize; i++)
{
total += randomNums[i];
if (randomNums[i] > biggest)
{
biggest = randomNums[i];
}
if (randomNums[i] < smallest)
{
smallest = randomNums[i];
}
}
average = ((float)total)/((float)aSize);
printf("Наибольшее случайное число: %d.\n",
biggest);
printf("Наименьшее случайное число: %d.\n",
smallest);
printf("Среднее из случайных чисел: %.2f.\n",
average);
// При использовании malloc, не забудьте
// использовать free
free(randomNums);
return(0);
}
Не могу понять, я же должен освободить память во всех ячейках? Почему в строчке free(randomNums) я освобождаю только нулевую ячейку памяти? Если бы не книга, то с помощью цикла я бы прошёлся по каждой ячейке и очистил ее. RandonNums же указатель на массив этих ячеек памяти, или я что-то напутал?
Другие языки программирования и технологии
Язык си, не могу понять динамическое выделение памяти.
Вы освобождаете не только ту ячейку памяти, на которую указывает указатель. К этой ячейке прицеплен сзади нее еще служебный блок памяти со структурой, в которой содержится разная информация, в том числе и о размере выделенного программе блока памяти. Функция malloc служит не только для нахождения свободного блока памяти заданного размера, но и для заполнения служебного блока памяти перед этим блоком, а возвращает указатель на начало только той части выделенной памяти, которая служит для размещения данных. Соответственно функция free находит по данном ей адресу не только начало памяти для данных, но и размещенный перед ней блок служебной информации, в котором указано, сколько памяти нужно освободить. При этом, естественно, освобождается не только память для данных, начинающаяся с указанного адреса, но и память, в которой перед этим адресом был размещен служебный блок информации.
И не считайте, что речь тут идет о реальной памяти - речь идет о виртуальной. В современных процессорах не зря миллиарды транзисторов, на самом деле всё гораздо сложнее, чем описывается в обычных пособиях, но ведь и обычному программисту всё это видеть, да и вообще знать об этом, и не надо. Это всё, так сказать, упрятано под ковер, на котором танцует пишущий программы программист.
И не считайте, что речь тут идет о реальной памяти - речь идет о виртуальной. В современных процессорах не зря миллиарды транзисторов, на самом деле всё гораздо сложнее, чем описывается в обычных пособиях, но ведь и обычному программисту всё это видеть, да и вообще знать об этом, и не надо. Это всё, так сказать, упрятано под ковер, на котором танцует пишущий программы программист.
Михаил Топоров
Вау, огромное спасибо за такой развернутый ответ, теперь все встало на свои места:)
А выделял ты тоже по одной ячейке? Если нет, то почему тебе пришла в голову идея освобождать по одной?
Дело в менеджере кучи. Он хранит не только адрес, но и размер занятой памяти по этому адресу. Поэтому освобождать ее можно "махом", даже не указывая размеров.
>Если бы не книга, то с помощью цикла я бы прошёлся по каждой ячейке и очистил ее.
Интересно, как бы тебе это удалось, если у тебя только ОДИН указатель...
> RandonNums же указатель на массив этих ячеек памяти, или я что-то напутал?
Ничего не напутал. Указатель на массив - это и есть указатель на его нулевой элемент.
Дело в менеджере кучи. Он хранит не только адрес, но и размер занятой памяти по этому адресу. Поэтому освобождать ее можно "махом", даже не указывая размеров.
>Если бы не книга, то с помощью цикла я бы прошёлся по каждой ячейке и очистил ее.
Интересно, как бы тебе это удалось, если у тебя только ОДИН указатель...
> RandonNums же указатель на массив этих ячеек памяти, или я что-то напутал?
Ничего не напутал. Указатель на массив - это и есть указатель на его нулевой элемент.
Михаил Топоров
Так если он указывает на на нулевой элемент, то и рассуждая логически функция free должна освободить память именно нулевой ячейки массива выделенной динамической памяти
Память выделяется не под каждый элемент в отдельности, а под весь массив сразу, одним цельным блоком. Поэтому и освобождается массив тоже весь целиком.
Менеджер памяти хранит список всех выделенных блоков, в котором записаны их адреса и размеры. Когда ты освобождаешь память он ищет в этом списке соответствующий адрес, смотрит сколько байтов выделялось и освобождает их все разом. Поэтому передаваемый функции free указатель должен быть тем же самым, который был возвращён функцией malloc. Если попытаться передать адрес какого-то произвольного элемента, то менеджер не найдёт нужный блок (потому что такого адреса нет в списке) и операция завершится ошибкой.
Менеджер памяти хранит список всех выделенных блоков, в котором записаны их адреса и размеры. Когда ты освобождаешь память он ищет в этом списке соответствующий адрес, смотрит сколько байтов выделялось и освобождает их все разом. Поэтому передаваемый функции free указатель должен быть тем же самым, который был возвращён функцией malloc. Если попытаться передать адрес какого-то произвольного элемента, то менеджер не найдёт нужный блок (потому что такого адреса нет в списке) и операция завершится ошибкой.
Похожие вопросы
- Вопрос для людей, знающих С/С++ -динамическое выделение памяти
- Помогите с решением задач по С по теме "Динамическое выделение памяти"!
- Задачка по нахождению суммы цифр числа на языке Си... Не могу разобраться с функциями Div и Fmod...
- Выделение памяти в C
- Почему язык СИ такой сложный?
- ПОМОГИТЕ ПОЖАЛУЙСТА ИСПРАВИТЬ КОД, НЕ МОГУ ПОНЯТЬ В ЧЁМ ПРИЧИНА, ПОЧЕМУ НЕ ПРАВИЛЬНО РАБОТАЕТ? ЯЗЫК СИ.
- Программирование на языке СИ с использованием подпрограммы-функции
- Выделение памяти и обращение к элементам C++
- Программирование на языке Си. Нужна небольшая помощь.
- какую программу лучше использовать для программирования на языке Си?