Q: So what's the right way to return a string or other aggregate?
A: The returned pointer should be to a statically-allocated buffer (as in the answer to question 7.5a), or to a buffer passed in by the caller, or to memory obtained with malloc, but not to a local (automatic) array.
For example, to have the caller pass space for the result:
	char *itoa(int n, char *retbuf)
	{
		sprintf(retbuf, "%d", n);
		return retbuf;
	}
	...
	char str[20];
	itoa(123, str);
To use malloc:
	#include <stdlib.h>
	char *itoa(int n)
	{
		char *retbuf = malloc(20);
		if(retbuf != NULL)
			sprintf(retbuf, "%d", n);
		return retbuf;
	}
	...
	char *str = itoa(123);
(In this last
case,
the caller must remember to free
the returned pointer when it is no longer needed.)
See also question 20.1.
Additional links: further reading