在C变量参数,如何使用泛型类型获取值? [英] Variable arguments in C, how to get values with a generic type?

查看:122
本文介绍了在C变量参数,如何使用泛型类型获取值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用C STDARG.H lib下,一个通用的类型。
int类型,是我的泛型类型>去了解它,请阅读举行。
所以,我的问题是:

I'm trying to use C stdarg.h lib, with a generic type. The type int, is my generic type > to understand it, please, hold reading. So, my problem is:

我有一个接受可变数量的参数的函数。像

I have a function that accept variable number of arguments. like

void function (int paramN, ...);

在我的计划中,有没有办法知道,这是可变参数的类型,它可以是一个字符,一个数组,一个int,一个短,一个功能点,等等......像

In my program, there are no way to know, which is the type of variable arguments, it can be a char, an array, an int, an short, an function point, etc... like

function (paramN, "Hey, I'm a string", 1, function_pint, array, -1); // -1 is a sentinel.

所以,我认为,一个int,是32位,在86(32位)系统,这将持有内存中的所有地址。所以,如果我得到一个INT所有的参数,它不会是一个问题,例如,嘿,我是一个字符串这个字符串的地址,在一个32位的变量通常适合,所以,我只需要做出铸造。

So, I think that, an int, is 32bits, in a x86(32bits) system, this will hold all address of memory. So, if I get all arguments with a int, it will not be a problem, for example, "Hey, I'm a string" the address of this string, fit normally in a 32bits variable, so, i need only to make a cast.

林权?

我能做到吗?

注:我不想让我的功能如printf(?这个解决方案,不适合在这种情况下,OK)

Im right?
Can I do it?
Note: I don't want to make my function like printf (this solution, don't fit in this case ok?)

感谢所有的答案。

很遗憾我的英语不好。

Thanks for all answer.
And sorry for my bad english.

推荐答案

您不能做到这一点,你描述它的方式。

You can't do it the way you describe it.

C调用约定是调用者把参数的堆栈上,但它并没有把任何类型的信息,因此,被调用方必须有办法找到它(变量至少大小)。

The C calling convention is for the caller to put arguments on the stack but it does not put any information on types, so the callee must have a way to find it (at least size of variables).


  • 对于每一个原型类型是已知的功能没问题。

  • No problem for functions with prototypes every type is known.

通过可变数字或参数(可变参数),它更棘手的功能,你必须调用的va_arg每个参数来读取每个变量,你必须提供在va_arg的类型。如果您提供一个类型,是不是真正一个编译器不会抱怨(它不能将它的运行时信息),但任何事情都有可能发生(通常是一件坏事)。

With functions with variable number or parameters (variadic) it's more tricky, you have to call va_arg for each argument to read each variable and you must provide the type for va_arg. If you provide a type that is not the real one the compiler won't complain (it can't it's runtime information) but anything can happen (usually something bad).

因此​​您必须传递类型。

在某些情况下,你可以predict类型。你可以通过它连接$ C $光盘格式字符串如printf确实,通过jldupont描述的联合把戏也够了常见的。

In some cases you can predict type (eg: a counter followed by some ints, and so on), but usually you pass it encoded in parameters. You can pass it encoded in a format string like printf does, the union trick described by jldupont is also common enough.

但无论如何你必须通过它。

But anyway you have to pass it.

您真的不能依赖于基础数据的二进制重新presentation,甚至没有数据大小。即使程序似乎工作,当你写它,它具有不兼容的,可以与该系统的任何变化打破了编译器,甚至改变编译选项时。

You really can't rely on underlying data binary representation, not even data size. Even if the program seems to work when you write it, it has no compatibility and can break with any change of the system, of the compiler, or even when changing compiling options.

让我们一起去,你通过type后跟参数(因此无论是工会招也不是格式字符串如printf)的例子。它的作用是将所有它传递的值增加一倍,并添加它们,没有真正有用的是不是:

Let's go with an example where you pass the type followed by the argument (thus neither the union trick nor the format string like printf). What it does is converting all it's passed value to double and add them, no really useful isn't it:

#include <stdio.h>
#include <stdarg.h>

enum mytypes {LONG, INT, FLOAT, DOUBLE };

double myfunc(int count, ...){
    long tmp_l;
    int tmp_i;
    double tmp_d;
    double res = 0;
    int i;

    va_list ap;
    va_start(ap, count);
    for(i=0 ; i < count; i++){
        int type = va_arg(ap, enum mytypes);
        switch (type){
            case LONG:
            tmp_l = va_arg(ap, long);
            res += tmp_l;
            break;
            case INT:
            tmp_i = va_arg(ap, int);
            res += tmp_i;
            break;
            case FLOAT:
            /* float is automatically promoted to double when passed to va_arg */
            case DOUBLE:
            tmp_d = va_arg(ap, double);
            res += tmp_d;
            break;
            default: /* unknown type */
            break;
        }
    }
    va_end(ap);
    return res;
}

int main(){
    double res;
    res = myfunc(5,
        LONG, (long)1,
        INT, (int)10,
        DOUBLE, (double)2.5,
        DOUBLE, (double)0.1,
        FLOAT, (float)0.3);
    printf("res = %f\n", res);
}

本例使用的新的的stdarg头文件可变参数C99中定义的头。要使用它,你需要至少有一个固定参数给你的函数(在本例是计数)。好东西如果这样,你可以在你的函数几个可变参数列表(也就是类似于 MYFUNC(INT COUNT1,...,INT COUNT2,...))。坏事是,​​你不能有一个纯粹的可变参数函数(即像MYFUNC(...)喜欢用的的格式。你仍然可以使用可变参数兼容的头文件使用旧格式,但它更复杂,很少有必要的,因为你需要的类型,但也有一些办法可以知道列表已完成,并像数是很方便的(但不这样做的唯一方式,终结者,可用于实例)。

This exemple use the new stdarg variadic header defined in C99. To use it you need to have at least one fixed parameter to your function (in this exemple it's count). The good thing if that thus you can have several variadic lists in your function (ie something like myfunc(int count1, ..., int count2, ...)). The bad thing is that you can't have a purely variadic function (ie something like myfunc(...) like with the old format. You can still use the old format using varargs compatibility headers. But it is more complicated and rarely necessary, because you need types but also some way to know the list is finished and something like count is handy (but not the only way to do it, a 'terminator' could be used for instance).

这篇关于在C变量参数,如何使用泛型类型获取值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆