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

时间:2015-07-07 22:15:40

标签: c variadic-functions

我的功能大致如此:

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舞会有任何奇怪的副作用吗?

3 个答案:

答案 0 :(得分:8)

是的,这是非常安全的。您不需要阅读所有可变参数只是为了阅读它们。您甚至不需要在TakesArgs内启动可变参数读取序列。

通常意味着执行任何参数传递维护任务的负担都赋予调用代码(它们的工作方式通常被认为是"传统的" C调用约定)。被叫者不必做任何事情。

答案 1 :(得分:2)

我认为这是安全的,尽管标准在这一点上并非非常明确。

N1570 7.16第3段说:

  

如果需要访问不同的参数,则调用函数   应在此声明一个对象(通常称为 ap   子条款)类型 va_list

请注意该句子的开头:" 如果需要访问不同的参数"。这意味着如果不需要访问不同的参数,则不需要声明va_list对象 - 这将导致无法调用va_startva_arg ,或va_end

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

  

如果没有相应的 va_start va_copy 的调用   宏,或者如果在返回之前未调用 va_end 宏,则   行为未定。

但是,根据上下文,我认为如果在调用va_end 之后未调用,则适用

答案 2 :(得分:1)

[回应评论时编辑。]

有些系统默认情况下弹出参数是被调用者的工作。这显然会让你陷入困境。 但是,正是由于这个原因,必须正确声明可变参数函数,并且声明必须对调用者正确可见。原因是在这些系统上,可变函数必须使用非默认的调用序列,其中调用者弹出参数,因为只有调用者可以确定有多少。所以只要你的函数被正确声明,你就应该是安全的。