指向可变大小参数的 C 函数指针
C function pointer to variable size arguments
我想在 C 中有一个通用函数指针,它只指定参数的数量,但它们的大小应该是任何类型。我以为下面的程序会崩溃,但不知何故,它确实可以在某些具有 64 位架构但不适用于 32 位架构的设备上运行。我不确定架构的广泛性是否是导致不同结果的原因。
#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;
}
有没有办法让它在任何架构上都能工作?
没有,没有。
它适用于 x64,因为前 4 个整数参数 are passed in the register rcx, rdx, r8 and r9。参数实际上有多大并不重要——无论如何,它们每个都获得一个 64 位寄存器。仅使用寄存器的底部。由于int
和char
和short
和long
都是这样传递的,所以你的程序运行,函数即将访问参数
不同的架构传递参数的方式不同。特别是,它们可能会被压入堆栈(x86 就是这样做的)。 char
和short
在push之前可能会转化为int
,但是int64_t
肯定不会。因此,在将参数压入堆栈的 32 位架构上,调用者压入 4*64 位,函数尝试读取 4*32 位,但它们没有正确排列。
更糟糕的是,在某些调用约定(例如 x86 __stdcall
)中,函数必须从堆栈中删除参数。如果您对该体系结构有错误的论点,它会破坏堆栈并使您的程序崩溃。
我想在 C 中有一个通用函数指针,它只指定参数的数量,但它们的大小应该是任何类型。我以为下面的程序会崩溃,但不知何故,它确实可以在某些具有 64 位架构但不适用于 32 位架构的设备上运行。我不确定架构的广泛性是否是导致不同结果的原因。
#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;
}
有没有办法让它在任何架构上都能工作?
没有,没有。
它适用于 x64,因为前 4 个整数参数 are passed in the register rcx, rdx, r8 and r9。参数实际上有多大并不重要——无论如何,它们每个都获得一个 64 位寄存器。仅使用寄存器的底部。由于int
和char
和short
和long
都是这样传递的,所以你的程序运行,函数即将访问参数
不同的架构传递参数的方式不同。特别是,它们可能会被压入堆栈(x86 就是这样做的)。 char
和short
在push之前可能会转化为int
,但是int64_t
肯定不会。因此,在将参数压入堆栈的 32 位架构上,调用者压入 4*64 位,函数尝试读取 4*32 位,但它们没有正确排列。
更糟糕的是,在某些调用约定(例如 x86 __stdcall
)中,函数必须从堆栈中删除参数。如果您对该体系结构有错误的论点,它会破坏堆栈并使您的程序崩溃。