【问题标题】:va_arg not working with doublesva_arg 不适用于双打
【发布时间】:2015-11-10 20:11:11
【问题描述】:

我有一个函数,它接受可变数量的参数,然后根据其他因素将每个参数传递给一个函数。这适用于大多数类型,无论它们是否是指针

func = (fmtfunc_t)dictobj(deflt, tok);
dat = func(va_arg(lst, void *));

fmtfunc_t 定义为

typedef char * (*fmtfunc_t)(void *);

此方法适用于例如以下功能

char *examp1(int i) {
    // i points to the correct integer value
}
char *examp2(char *s) {
    // s points to the correct string value
}

但是,当参数是 double 时,它不起作用

char *examp3(double d) {
    // d is 0
}

我知道issuesva_arg 和双重提升,但我不相信这是我问题的根源。我这样调用函数

func(23.4);

如您所见,参数是 double 文字,所以我认为我不应该关心促销问题。

为什么va_argdoubles 返回一个不正确的值,但没有为任何其他类型返回?我是否遇到了某种未定义的行为,并且对double 以外的类型感到幸运?

【问题讨论】:

  • 如果i“指向”examp1 的整数,那么已经有问题了。该函数需要一个整数,而不是指针。提供带有可变参数函数声明的minimal reproducible example。作为给定,你不能这样称呼它,因为你缺少一个命名参数。
  • 问题不在于va_arg。问题在于您使用fmtfunc_t。这违反了 6.5.2.2(9) “如果函数定义的类型与表示被调用函数的表达式所指向的(表达式的)类型不兼容,行为未定义。”
  • @RaymondChen 谢谢你,我将不得不改变我这样做的方式。 (at)Olaf 我试图使示例尽可能简短,所以我会添加更多,但我不确定现在是否有必要,因为我知道这是未定义的行为。
  • 其实再看一遍,问题也在va_arg。 7.15.1.1(2):“如果 type 与实际下一个参数的类型不兼容(根据默认参数提升),行为未定义 ,但以下情况除外[均不适用]。”我猜你看到问题的原因只是 doubleintvoid* 以相同的方式传递(在 GP 寄存器中),但 double 在 FP 寄存器中传递。
  • 你正在尝试做的事情是行不通的。您不能简单地获取任何类型的参数并期望它起作用。

标签: c variadic-functions


【解决方案1】:

正如 @RaymondChen、@Olaf 和 @FUZxxl 在 cmets 中指出的那样,问题在于,通过使用类型与声明不兼容的参数调用函数

char *examp(int i);

fmtfunt_t func = examp;
func(va_arg(lst, void *)); //called with an argument of void*, but the parameter is of type int

我导致了未定义的行为。我通过获取参数作为适当的类型解决了这个问题

double arg = va_arg(lst, double);

而不是试图将void * 用作包罗万象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-20
    • 2013-12-19
    • 1970-01-01
    • 2023-02-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-02
    • 2015-05-14
    相关资源
    最近更新 更多