简体   繁体   English

具有double类型的可变数字参数的函数的奇怪输出

[英]Strange output for function with variable number parameters of type double

I tried function with variable number of integer parameters, it worked as expected. 我尝试了具有可变数量的整数参数的函数,它按预期工作。 But when I tried variable number of parameters of type "double", it gave strange output: 但是当我尝试可变数量的“double”类型的参数时,它给出了奇怪的输出:

$ g++ -fpermissive -std=c++11 te2d.cc
te2d.cc: In function ‘void maxof(double, long int, ...)’:
te2d.cc:19:16: warning: return-statement with a value, in function returning 'void' [-fpermissive]
$ ./a.out
dum=100.200000
debug 1 0.000000
debug 2 0.000000
debug 3 -5486124068793688683255936251187209270074392635932332070112001988456197381759672947165175699536362793613284725337872111744958183862744647903224103718245670299614498700710006264535590197791934024641512541262359795191593953928908168990292758500391456212260452596575509589842140073806143686060649302051520512.000000
debug 4 0.000000

Here is the short code: 这是简短的代码:

#include <stdio.h>
#include <stdarg.h>
typedef unsigned char uchar;
typedef unsigned short uint16;
using namespace std;
typedef unsigned char uchar;
void maxof(double dum, long n_args, ...){
        printf("dum=%f\n", dum);
        register int i;
        int max = 0;
        va_list ap;

        va_start(ap, n_args);
        for(i = 1; i <= n_args; i++) {
            printf("debug %d %f\n", i, va_arg(ap, double));
        }

        va_end(ap);
        return max;
}

int main(int argc, char *argv[]) {
    maxof(100.2, 4, 10,14,13,11);
    return 0;
}

Any ideas? 有任何想法吗? Thanks. 谢谢。

C variadic functions don't magically handle conversions from int to double *. C变量函数不会神奇地处理从intdouble *的转换。 You need to specify the type that went into the function, not the type you want to end up with after conversions. 您需要指定进入函数的类型,而不是转换后要结束的类型。 Think of it as telling the compiler how to interact with the stack. 可以把它想象成告诉编译器如何与堆栈交互。 If you tell it the top of the stack has a double and double is bigger than int , you've now just told it to take extra bytes off of the stack, which is terrible. 如果你告诉它堆栈的顶部有一个doubledoubleint ,你现在只是告诉它从堆栈中取出额外的字节,这很糟糕。 Even if they were the same size, they do not have the same binary representation. 即使它们的大小相同,它们也没有相同的二进制表示。

You really have to be careful with C variadic functions. 你必须要小心C变量函数。 The better solution, if available, would be to use variadic templates, which are perfectly typesafe and trigger compile-time errors rather than undefined behaviour. 更好的解决方案(如果可用)将使用可变参数模板,这些模板是完全类型安全的并且触发编译时错误而不是未定义的行为。 In this case, since you want all arguments to be the same type, you can use std::initializer_list : 在这种情况下,由于您希望所有参数都是相同的类型,因此您可以使用std::initializer_list

#include <initializer_list> //be sure not to forget this when using std::initializer_list

double maxof(std::initializer_list<double> nums) {
    double max = 0; //hope you don't have negative numbers
    for (const auto &num : nums) {
        if (num > max) {max = num;}
    }

    return max;
}

...

maxof({10,14,13,11})

Note that there's an overload of std::max that does this, so no need to write your own. 请注意, std::max的重载会执行此操作,因此无需编写自己的。

If you're stuck with pre-C++11, you could potentially create many overloads to get the same effect, but you'd be much better off creating a function based on a container or iterators, like std::max_element . 如果你坚持使用pre-C ++ 11,你可能会创建许多重载来获得相同的效果,但是你可以更好地创建一个基于容器或迭代器的函数,比如std::max_element


*Promotions are applied to arguments, so it's not always the exact type that goes in. For example, passing in a char will require the function to extract an int . *促销应用于参数,因此它并不总是确切的类型。例如,传入char将需要函数提取int These promotions are well-specified and are mostly <small integral type> -> int . 这些促销很明确,主要是<small integral type> - > int

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM