Broken C code: followup

I received a number of comments on my previous blog post, with people stating that my example code wasn't right, either.

For reference, here's my code snippet again:

#include <stdio.h>
void* f();
int main() {
	long* a;
	a=(long*)f();
	printf("%Ld\n", *a);
	return 0;
}

void* f() {
	static long a=84;
	printf("%Ld\n", a);
	return &a;
}

First, let me make one thing perfectly clear: the "a" variable is not on the stack. It is a locally-scoped variable, but it is also declared as static, meaning that it's valid for the entire run of the process; if it were on the stack, then this variable would vanish when the function would end. Yes, it's wrong to return a pointer to a variable on the stack, since there's no guarantee that the stack value will still be valid; but I'm not doing that.

Alternative implementations could've used a global variable, or could've malloc()'ed a pointer; but the compiled assembly code for my C code will only differ from a version with a global variable in the used label for the variable's location, and in the lack of an extra function call from a version that uses malloc().

Second, no, using A0 as a return value for pointers is not a bug in the compiler, and has not been since 1990, when this interesting book entitled "System V ABI Motorola 68000 Processor Family Supplement" was written. Allow me to quote a snippet from page 3-14 of that book:

%a0Pointer return values appear in %a0. When calling a function that returns a structure or union, the caller allocates space for the return value and sets %a0 to its address. A function that returns a structure or union value places the same address in %a0 before it returns.

To this day, ELF-conforming implementations do it this way. Really. Go look it up, if you wish; the ISBN is 0-13-877663-6.