Одной из возможностей является передача функции указателя:
void computeFoo(int *dest) {
*dest = 4;
}
Это хорошо, потому что вы можете использовать такую функцию с автоматической переменной:
int foo;
computeFoo(&foo);
При таком подходе вы также сохраняете управление памятью в той же части кода, т.е. вы не можете пропустить malloc только потому, что это происходит где-то внутри функции:
// Compare this:
int *foo = malloc(…);
computeFoo(foo);
free(foo);
// With the following:
int *foo = computeFoo();
free(foo);
Во втором случае легче забыть бесплатное, так как вы не видите malloc. Часто это по крайней мере частично решается соглашением, например: «Если имя функции начинается с XY, это означает, что вы владеете данными, которые она возвращает».
Интересный случай возврата указателя на переменную «function» - объявление статической переменной:
int* computeFoo() {
static int foo = 4;
return &foo;
}
Конечно, это плохо для нормального программирования, но когда-нибудь это может пригодиться.