完全忽略 C 函数的可变参数是否安全?

Is it safe to completely ignore variadic arguments to a C function?

我有一个大致如下所示的函数:

typedef struct SomeType {
  ...
} SomeType;

void TakesArgs(SomeType *t1, ...) {
     // iterates through arguments
}

// usage:
TakesArgs(&a, &b, &c);

如果我将 TakesArgs 更改为空操作,同时仍然保持所有调用代码不变,我 运行 是否会存在内存(或其他方面)的任何奇怪风险?

void TakesArgs(SomeType *t1, ...) {
    return;
}

// usage unchanged: 
TakesArgs(&a, &b, &c);

换句话说,跳过原实现中执行的va_list/va_start舞蹈会不会有什么奇怪的副作用?

是的,绝对安全。您不需要为了阅读而阅读所有可变参数。您甚至不需要在 TakesArgs.

内启动可变参数读取序列

在幕后,它通常意味着执行任何参数传递维护任务的负担被赋予了调用代码(它们以通常被认为是 "traditional" C 调用约定的方式工作)。被叫方不需要做任何事情。

[根据评论进行编辑。]

有些系统默认弹出参数是被调用者的工作。那显然会给你带来麻烦。 但是,正是由于这个原因,必须正确声明可变参数函数,并且声明必须对调用者正确可见。原因是在那些系统上,可变参数函数必须使用调用者弹出参数的非默认调用序列,因为只有调用者才能确定有多少。所以只要你的函数被正确声明,你就应该是安全的。

我相信它是安全的,尽管标准在这一点上相当明确。

N1570 7.16 第 3 段说:

If access to the varying arguments is desired, the called function shall declare an object (generally referred to as ap in this subclause) having type va_list.

请注意该句子的开头:“If 需要访问不同的参数”。这意味着如果不需要访问不同的参数,则无需声明 va_list 对象——这将导致无法调用 va_startva_argva_end.

一个可能的反驳是 va_end (N1570 7.16.1.3) 的描述说:

If there is no corresponding invocation of the va_start or va_copy macro, or if the va_end macro is not invoked before the return, the behavior is undefined.

但是,考虑到上下文,我认为如果 va_end 未被调用 va_start 被调用后适用