据我所知,C变量参数完全由被调用者处理,即如果您使用调用函数f
f(1, 2, 3.0)
无论您是否已将f
声明为,编译器都会为调用生成相同的代码
void f(int, int, double);
或
void f(int, int, ...);
这个问题的上下文是用可变FFI定义从Rust调用一个不是真正的可变C函数的问题。如果从调用方的角度来看(当然除了类型检查之外)变量不重要,那么Rust会为函数被声明为变量的调用生成不同的代码,这对我来说似乎很奇怪。
如果这实际上不是由C规范决定的,而是取决于ABI的,那么我最感兴趣的是System V ABI的答案,从我所读到的内容来看,它似乎并没有表明调用方对变体有任何特殊处理。
这是一个非ABI特定的答案。
是的,在形式上,调用者可以(在一般情况下,也会)以一种特殊的方式处理带有可变参数的函数。这实际上就是为什么从标准化时代开始,C语言就要求所有变差函数在调用点之前用原型声明的原因。请注意,尽管在C89/90中可以安全地调用未声明的函数,但这样做的权限并没有扩展到varadic函数:这些函数总是必须提前声明的。否则,行为是未定义的。
在一个稍微不同的形式中,该规则仍然适用于现代C。尽管C99之后的C不再允许调用未声明的函数,但它仍然不需要原型声明。然而,变量函数必须在调用点之前用原型声明。基本原理是一样的:调用者必须知道它正在调用一个可变函数,并且可能以不同的方式处理调用。
历史上,有些实现在调用可变函数时使用了完全不同的调用约定。