The problem with the description of what is happening is in step 2. If the declaration is implicit, the code on the calling site does not "convert" the return value of the function, really.
What happens is that the calling site code retrieves the return value (usually from the register or from the stack), assuming it is of type int. The procedure for this is different for different OS and compilers and is usually defined by an ABI document.
For the most common ABIs, the return location and the sizes of int and void * are the same, so in fact you will not have any problems with this, although this is not true. This is true for Linux, Windows, and Mac OS X on both 32-bit and 64-bit platforms, I believe that it is 32-bit platforms.
On 64-bit platforms, more often for "long" and "void *" should be the same size, so if you have an implicit declaration for malloc (), the return value will be truncated. Nevertheless, several popular 64-bit programming models.
Back in the "good old days" of DOS development, it was possible to create programs that started in a mode where "int" was 16 bits and the pointers were 32 bits (in fact, 24). In these cases, calling malloc () with an implicit prototype would truncate the return value.
Note that even in cases where the return value is truncated, you still may not have a run-time problem, depending on whether the value is really outside the valid int range.
On Mac OS X in 64-bit mode, this code:
#include <stdio.h> int main (int argc, const char * argv[]) { int x = malloc(128); void *p = malloc(128); printf("Hello, World!\nsizeof(int)=%d,sizeof(void*)=%d,x=0x%xd,p=%p\n", sizeof(int), sizeof(void *), x, p); return 0; }
prints:
Hello World! SizeOf (INT) = 4, SizeOf (* invalid) = 8, x = 0x1001c0d, p = 0x100100240
Note that the “x” value has fewer digits than the “p” value, silently resetting the most significant 32 bits of the value. The actual build code for two malloc calls is as follows:
LM2: movl $128, %edi call _malloc movl %eax, -12(%rbp) LM3: movl $128, %edi call _malloc movq %rax, -8(%rbp)
So, the correct value is returned by malloc (in% rax), but the movl command truncates it when it moves to the variable "x".