I would like to have an universal function pointer in C which only specifies the number of arguments, but their size should be of any kind. I thought the following program would crash, but somehow it does work on some devices with 64 Bit architecture but not on 32 Bit. I am not sure if the wideness of architecture is the reason for the different results.
#include <stdio.h>
#include <stdlib.h>
typedef int METHOD(int64_t, int64_t, int64_t, int64_t);
int foo(int i, char c, short s, long l){
printf("i: %d, c: %c s: %hd l:%ld\n", i, c, s, l);
return 5;
}
int main(int argc, char ** argv){
METHOD * ptr=(METHOD*)&foo;
printf("res: %d\n",
ptr(1,'2',3,4));
printf("res: %d\n",
foo(1,'2',3,4));
return 0;
}
Is there a way to make this work on any architecture?
No, there is not.
It works on x64 because the first 4 integer parameters are passed in the register rcx, rdx, r8 and r9 . It doesn't matter how big the parameters actually are - they each get a 64-bit register regardless. Only the bottom part of the register is used. Since int
and char
and short
and long
are all passed this way, your program runs and the function is about to access the parameters.
Different architectures pass parameters differently. In particular, they may be pushed on the stack (x86 does this). char
and short
might be converted to int
before pushing, but int64_t
certainly will not. So on a 32-bit architecture which pushes arguments on the stack, the caller pushes 4*64 bits, and the function tries to read 4*32 bits, and they don't line up correctly.
Even worse, in some calling conventions (eg x86 __stdcall
) the function has to remove the arguments from the stack. If you have the wrong arguments on this architecture, it corrupts the stack and crashes your program.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.