在C语言中,调用程序是否专门处理变量?

在C语言中,调用程序是否专门处理变量?,c,variadic-functions,calling-convention,C,Variadic Functions,Calling Convention,据我所知,C变量参数完全由被调用方来处理,即如果调用函数f f(1, 2, 3.0) 无论您是否将f声明为 void f(int, int, double); 或 这个问题的背景是使用可变FFI定义从Rust调用非真正可变的C函数。如果从调用者的角度来看变量无关紧要(当然除了类型检查之外),那么Rust会为函数声明为变量的调用生成不同的代码,这对我来说似乎很奇怪 如果这实际上不是由C规范决定的,而是由ABI决定的,那么我最感兴趣的是对的答案,从我读到的内容来看,它似乎没有表明调用方对变量的任

据我所知,C变量参数完全由被调用方来处理,即如果调用函数
f

f(1, 2, 3.0)
无论您是否将
f
声明为

void f(int, int, double);

这个问题的背景是使用可变FFI定义从Rust调用非真正可变的C函数。如果从调用者的角度来看变量无关紧要(当然除了类型检查之外),那么Rust会为函数声明为变量的调用生成不同的代码,这对我来说似乎很奇怪


如果这实际上不是由C规范决定的,而是由ABI决定的,那么我最感兴趣的是对的答案,从我读到的内容来看,它似乎没有表明调用方对变量的任何特殊处理。

这是一个非ABI特定的答案

是的,在形式上,调用者可以(并且,在一般情况下,将)以一种特殊的方式处理具有可变参数的函数。这实际上就是为什么从标准化时代开始,C语言就要求在调用点之前用原型声明所有可变函数的原因。请注意,尽管可以安全地调用C89/90中未声明的函数,但这样做的权限并未扩展到可变函数:这些函数始终必须事先声明。否则,该行为未定义

以一种稍微不同的形式,该规则仍然存在于现代C中。尽管C99后C不再允许调用未声明的函数,但它仍然不需要原型声明。然而,变量函数必须在调用点之前用原型声明。原理是一样的:调用者必须知道它正在调用一个可变函数,并且可能以不同的方式处理调用


历史上,有一些实现在调用可变函数时使用完全不同的调用约定。

这是一个非ABI特定的答案

是的,在形式上,调用者可以(并且,在一般情况下,将)以一种特殊的方式处理具有可变参数的函数。这实际上就是为什么从标准化时代开始,C语言就要求在调用点之前用原型声明所有可变函数的原因。请注意,尽管可以安全地调用C89/90中未声明的函数,但这样做的权限并未扩展到可变函数:这些函数始终必须事先声明。否则,该行为未定义

以一种稍微不同的形式,该规则仍然存在于现代C中。尽管C99后C不再允许调用未声明的函数,但它仍然不需要原型声明。然而,变量函数必须在调用点之前用原型声明。原理是一样的:调用者必须知道它正在调用一个可变函数,并且可能以不同的方式处理调用


历史上,有一些实现在调用可变函数时使用完全不同的调用约定。

我相信这取决于ABI。@EugeneSh。如果是这样的话,我已经更新了我的问题,以反映我最关心的是SystemV ABI,这似乎是SystemV ABI的复制品;有什么区别吗?没有单一的系统V ABI!这取决于阿比,我相信…@EugeneSh。如果是这样的话,我已经更新了我的问题,以反映我最关心的是SystemV ABI,这似乎是SystemV ABI的复制品;有什么区别吗?没有单一的系统V ABI!还请注意,可变参数受类型提升的影响,这些类型提升不一定与在存在非可变原型的情况下执行的类型提升相同。@JohnBollinger:这可能是要求声明的实际原因,而不是潜在的不同ABI。例如,AAPCS使用与固定参数列表函数相同的约定。@Olaf:但这些提升与调用具有非原型声明或(在C89/90的情况下)完全没有声明的函数时执行的提升相同。这立即意味着不,这不是要求原型的实际原因。还要注意,可变参数的类型升级不一定与在非可变原型存在时执行的类型升级相同。@JohnBollinger:这可能是要求声明的实际原因,没有潜在的不同ABI。例如,AAPCS使用与固定参数列表函数相同的约定。@Olaf:但这些提升与调用具有非原型声明或(在C89/90的情况下)完全没有声明的函数时执行的提升相同。这立刻意味着不,这不是需要原型的实际原因。
void f(int, int, ...);