Я прошу прощения за добавление еще одного ответа, но я не думаю, что кто-то охватил все вопросы, которые необходимо охватить в вашем вопросе.
1) Всякий раз, когда вы используете malloc()
для динамического выделения некоторой памяти,Вы также должны free()
это, когда вы закончите.Операционная система обычно приводит в порядок после вас, но учтите, что у вас есть процесс во время вашего исполняемого файла, который использует некоторое количество памяти.Когда указанный процесс завершен, если вы free()
этой памяти, ваш процесс имеет больше доступной памяти.Это касается эффективности.
Чтобы использовать бесплатно правильно:
int* somememory = malloc(sizeyouwant * sizeof(int));
// do something
free(somememory);
Легко.
2) Всякий раз, когда вы используете malloc
, как уже отмечали другие, фактическое распределение в байтах, так что выдолжен сделать malloc(numofelements*sizeof(type));
.Есть еще одна, менее широко используемая функция под названием calloc
, похожая на эту calloc(num, sizeof(type));
, которую, возможно, легче понять. calloc также инициализирует вашу память на ноль .
3) Вам не нужно приводить тип возвращаемого значения malloc
.Я знаю, что многие книги по программированию предлагают вам и C ++ мандаты, которые вы должны (но в C ++ вы должны использовать new
/ delete
).См. этот вопрос .
4) Ваша сигнатура функции действительно неверна - сигнатуры функций должны совпадать с их функциями.
5) При возврате указателей из функций это то, что яобескуражить, но это не так само по себе.Два момента, о которых стоит упомянуть: всегда помните 1).Я спросил , в чем именно заключается проблема, и все сводится к отслеживанию этих free()
вызовов.Как более опытный пользователь, есть еще тип распределителя, о котором нужно беспокоиться.
Еще один момент, рассмотрим эту функцию:
int* badfunction()
{
int x = 42;
int *y = &x;
return y;
}
Это плохо, плохо, плохо.Здесь происходит то, что мы создаем и возвращаем указатель на x
, который существует, пока вы находитесь в badfunction
.Когда вы возвращаетесь, у вас есть адрес переменной, которая больше не существует , потому что x
обычно создается в стеке.Вы узнаете больше об этом со временем;сейчас просто подумайте, что переменная не существует вне ее функции.
Обратите внимание, что int* y = malloc(...
- это другой случай - память создается в куче из-за malloc и, следовательно, сохраняется в конце указанногоfunction.
Что бы я порекомендовал в качестве сигнатуры функции?Я бы на самом деле пошел с функцией shybovycha с небольшой модификацией:
int findFactors(int* factors, const int N);
Мои изменения - это просто личные предпочтения.Я использую const
, чтобы я знал, что что-то является частью ввода функции.Это не обязательно просто с помощью int, но если вы передаете указатели, помните, что исходная память может быть изменена, если вы не используете const
перед этим, и ваш компилятор должен предупредить вас, если вы попытаетесь ее изменить.Так что в данном случае это просто привычка.
Второе изменение заключается в том, что я предпочитаю выходные параметры слева, потому что я всегда так думаю, т. Е. output = func(input)
.
Почему вы можете изменять аргументы функциикогда указатель используется?Потому что вы передали указатель на переменную.Это просто адрес памяти - когда мы «разыменовываем» его (обращаемся к значению по этому адресу), мы можем его изменить.Технически говоря, C строго передается по значению.Сами указатели являются переменными, содержащими адреса памяти, и содержимое этих переменных копируется в вашу функцию.Поэтому обычная переменная (скажем, int
) - это просто копия того, что вы передали. int* factors
- это копия адреса в переменной указателя, которую вы передаете. По замыслу и оригинал, и эта копия указывают на одно и то жепамять, поэтому, когда мы разыменовываем их, мы можем редактировать эту память как в вызывающей, так и в исходной функции.
Надеюсь, это прояснит некоторые вещи.