简体   繁体   中英

C function pointer to variable size arguments

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM