One possibility is passing the function a pointer:
void computeFoo(int *dest) {
*dest = 4;
}
This is nice because you can use such a function with an automatic variable:
int foo;
computeFoo(&foo);
With this approach you also keep the memory management in the same part of the code, ie. you can’t miss a malloc just because it happens somewhere inside a function:
// Compare this:
int *foo = malloc(…);
computeFoo(foo);
free(foo);
// With the following:
int *foo = computeFoo();
free(foo);
In the second case it’s easier to forget the free as you don’t see the malloc. This is often at least partially solved by convention, eg: “If a function name starts with XY, it means that you own the data it returns.”
An interesting corner case of returning pointer to “function” variable is declaring the variable static:
int* computeFoo() {
static int foo = 4;
return &foo;
}
Of course this is evil for normal programming, but it might come handy some day.