Tag: variadic functions

gcc中的运行时参数(反向va_args / varargs)

我正在尝试对我正在研究的微控制器的解释器进行一些改进。 为了执行内置函数,我目前有这样的东西(虽然有点快): function executeBuiltin(functionName, functionArgs) { if (functionName==”foo”) foo(getIntFromArg(functionArgs[0])); if (functionName==”bar”) bar(getIntFromArg(functionArgs[0]),getBoolFromArg(functionArgs[1]),getFloatFromArg(functionArgs[2])); if (functionName==”baz”) baz(); … } 但它适用于资源非常有限的嵌入式设备(ARM),我需要大幅减少代码大小。 我想做的是有一个通用函数来调用具有不同参数的其他函数 – 如下所示: function executeBuiltin(functionName, functionArgs) { functionData = fast_lookup(functionName); call_with_args(functionData.functionPointer, functionData.functionArgumentTypes, functionArgs); } 所以我希望能够调用标准的C函数并将其传递给它所需的任何参数(可能都是不同的类型)。 为此,我需要一个call_with_args函数。 我想避免重写每个函数来采取argc + argv。 理想情况下,每个被调用的函数都是完全标准的C函数。 这里有一个关于这个问题的讨论 – 但自1993年撰写该帖以来,有什么变化吗? 特别是当我在ARM上运行时,参数位于寄存器而不是堆栈中。 即使它不在标准C中,是否有任何GCC具体可以完成? 更新:看起来尽管根据规范行为是“未定义的”,看起来因为C调用的方式工作,你可以传递更多的参数到一个函数而不是它期望的一切都很好,所以你可以解压缩所有将参数放入uint32s数组中,然后可以将每个uint32传递给该函数。 这使得为​​调用编写“漂亮”代码变得更加容易,并且它似乎运行得很好(在32位平台上)。 唯一的问题似乎是传递64位数字并编译为64位x86,因为在这种情况下它似乎做了一些特别奇怪的事情。

C中的可变参数scanf

我很好奇是否有可能在C中实现一种可变版本的scanf 。我的意思是如果输入是push (1 2 3) , scanf将能够解析为%s %d %d %d像scanf(“%s (%d)”, string, some_list) 。 它将占用%d所有实例并将它们(按顺序)附加到列表中…… 我在说感觉吗? 编辑:对于指定的输入, string == “push”和some_list == [1, 2, 3] 。

使用var_arg传递函数调用的参数

我正在编写一个适配器来组合两个API(一个在C中,另一个在C ++中)。 如果在一个API上调用一个函数,我需要将调用者ID和函数的参数传递给适配器,并在传递此信息的情况下调用相应的函数。 现在显然它们无法直接映射,因为一个接口需要C ++编译,名称修改会使另一个接通,所以这就是我首先使用一组适配器的原因。 由于参数的数量不同,我查找了可变参数函数,并发现这个想法非常有用,但是我只在POD上运行,并且必须处理每个调用的结构,枚举和许多不同的参数,这可能需要放回去在将其提供给目标函数之前进入结构体。 我偶然发现的每个例子都比较简单,主要涉及算术操作,例如总结,查找最大数字或打印。 主要使用var_list上的for循环完成。 也许我陷入了这个想法,它根本不起作用,但我只是好奇…… 假设我想将列表中的参数分配给我的目标函数参数(传递的参数的顺序是正确的),这会是一个好方法吗? BOOL Some_Function( /* in */ CallerId *pObjectId, /* in */ someDataType argument1 ) { BOOL ret = Adapter_Call(pFunction, pObjectId, argument1); return ret; } 所以一旦我把它做成了正确的适配器,我想做 BOOL Adapter_Call(*pFunction, *pObjectId, argument1, …) { va_list args; va_start(args, argument1); /*go over list and do `var_list[i] = pFunctionArgList[i]` which is of […]

在C89中使用可变参数函数而不传递参数或最终参数?

假设我有一个可变函数foo(int tmp, …) ,当调用foo函数时我需要知道有多少个参数。 我知道有两种方法可以找出有多少参数: 在调用foo时使用最后一个参数,比如-1,所以你的函数调用将是这样的: foo(tmp, 1, 2, 9, -1) ,当你在foo内部并且va_arg调用返回-1时你知道你已阅读所有函数参数 在foo中再添加一个参数,程序员将拥有参数总数,因此你可以像这样调用foo: foo(tmp, 5, 1, 2, 3, 4, 5) foo(tmp, 2, 7, 8) foo(tmp, 5, 1, 2, 3, 4, 5)或foo(tmp, 2, 7, 8) 我曾经遵循第一种方式,曾经有过以下错误。 随着代码: expr_of_type(expr, boolexpr_e, newtable_e, nil_e, -1) 其中expr_of_type是一个可变参数函数,并检查expr(第一个参数)是否是以下类型之一(boolexpr_e或new_table_e或nil_e具有所有类型的枚举类型)。 我一个人意外地写道: expr_of_type(expr, boolexpr_e, newtable_e, nil_e -1) 我忘记了nil_e和-1之间的逗号,因为nil_e有一个枚举类型,nil_e – 1是一个有效的表达式,因为nil_e不是0,当尝试获取expr_of_type参数时,给定的可变参数函数没有找到-1作为最后一个参数继续搜索创建一个花了我一些时间才发现的bug。 我也没有找到第二种方式,因为当从可变参数函数中添加或删除一个参数时,您需要更改包含总参数数量的参数。 在寻找更好的使用/创建可变参数函数的方法时,我发现了可变元宏 ,它可以解决我在使用第一种方式时遇到的错误。 但是可变参数宏可用于C99标准。 […]

仅在使用vararg省略号时,函数指针“从不兼容的指针类型分配”

我知道声明一个没有参数列表的函数(或函数指针)(并且在参数列表中没有指定void ),这意味着函数(或函数指针)具有未知数量的参数。 我写了一些测试脚本来检查这种行为: int my_func_1() { return(0); } int my_func_2(int x) { return(x); } int my_func_3(char x, …) { va_list va; va_start(va, x); return(va_arg(va, int)); } int (*fp)(); fp = my_func_1; printf(“%d\n”, fp()); fp = my_func_2; printf(“%d\n”, fp(33)); fp = my_func_3; printf(“%d\n”, fp(33, 44)); 我在linux下的64位机器上编译了这样的: gcc test.c -Wextra -pedantic -std=c1x -O3 -o test 输出是正确的: 0 […]

传递具有未确定数量的参数的函数,并使用可变参数调用它

我想创建一个函数“lazy”,它接受一个具有未确定数量的参数作为参数的函数。 我需要什么类型或必须完成哪些演员表? 然后我想在函数“evaluate”中执行该事情。 然后我如何将之前传递的参数传递给传递函数指针的“lazy”函数? 一些代码来说明我的问题: char *function_I_want_to_call(void *foo, type bar, …); // the arguments are unknown to lazy() and evaluate() typedef struct { ??? func; va_list args; } lazy_fcall; void lazy(lazy_fcall *result, ??? func, …) { // which type do I need here? va_start(result->_args, fund); result->func = func; } void *evaluate(lazy_fcall *to_evaluate) { return to_evaluate->func(expand_args(to_evaluate->args)); […]

抑制“ISO C99需要使用rest参数”

考虑以下两个宏: #define PNORM( v, s, … ) { \ if( VERBOSITY_CHECK( v ) ) { \ if( ( errno = pthread_mutex_lock(&server.output_mutex) ) ) { \ PERROR_LOCKFREE( normal, “\tpthread_mutex_lock failed on output_mutex.\r\n” ) ; \ } \ fprintf( stdout, s, ## __VA_ARGS__ ) ; \ fflush( stdout ) ; \ if( ( errno = pthread_mutex_unlock(&server.output_mutex) ) […]

宏中的__VA_ARGS__是什么意思?

/* Debugging */ #ifdef DEBUG_THRU_UART0 # define DEBUG(…) printString (__VA_ARGS__) #else void dummyFunc(void); # define DEBUG(…) dummyFunc() #endif 我在C编程的不同标题中看到了这种符号,我基本上理解它是通过参数,但我不明白这个“三点符号”是什么叫? 有人可以通过示例解释它或提供有关VA Args的链接吗?

与vsprintf和va_list的平台不一致

背景:我目前正在尝试“扩展”标准C格式,支持处理某个结构,类似于Objective-C扩展C格式以允许支持带有“%@”序列的NSString。 我正在努力解决的一个问题是vsprintf在OS X和Linux上的表现似乎不同(我用Ubuntu 10.10和12.04测试过)。 在OS X上,它表现得我认为应该如何,在调用vsprintf之后,调用va_arg返回ms指针(好像vsprintf函数调用va_arg来获取5)。 但是,在Linux上,va_list不会从vsprintf更改,并且调用va_arg将返回5。 我真的想找到一种方法来实现这个function,以便它在不同平台上表现一致。 假设您可以期望vsprintf始终更改va_list中的指针以便下次调用va_arg它返回下一个尚未使用的参数时,这是错误的吗? 我尽可能地简化了我的代码来演示这个问题。 在OS X上,此代码打印从malloc返回的指针的正确地址。 在Linux上,foo中ms的值变为5,因此它打印5。 #include #include #include #include static void foo(void *, …); typedef struct { char *value; } mystruct; int main(int argc, char *argv[]) { mystruct *ms = malloc(sizeof(mystruct)); foo(NULL, “%d %@”, 5, ms); } void foo(void *dummy, …) { va_list args; va_start(args, dummy); char […]

我们可以将va_arg与工会一起使用吗?

6.7.2.1我的C99标准草案第14段有关于工会和指针的说法(强调,一如既往地增加): 联合的大小足以容纳其中最大的成员。 最多一个成员的值可以随时存储在union对象中。 指向适当转换的并集对象的指针指向其每个成员(或者如果成员是位字段,则指向它所在的单位),反之亦然。 一切都很好,这意味着执行类似下面的操作是合法的,将signed或unsigned int复制到union中,假设我们只想将其复制到相同类型的数据中: union ints { int i; unsigned u; }; int i = 4; union ints is = *(union ints *)&i; int j = is.i; // legal unsigned k = is.u; // not so much 7.15.1.1第2段有这样的说法: va_arg宏扩展为具有指定类型的表达式和调用中下一个参数的值。 参数ap应该由va_start或va_copy宏初始化(没有为va_copy调用va_end宏)。 每次调用va_arg宏都会修改ap以便依次返回连续参数的值。 参数type应该是指定的类型名称,以便可以通过将*到type来获得指向具有指定类型的对象的指针的type 。 如果没有实际的下一个参数, 或者type与实际的下一个参数的类型不兼容(根据默认参数提升而提升),则行为是未定义的,除了以下情况: -one type是有符号整数类型,另一种类型是相应的无符号整数类型,并且该值可在两种类型中表示; -one类型是指向void的指针,另一个是指向字符类型的指针。 我不打算引用关于默认参数促销的部分。 我的问题是:这是定义的行为: void func(int i, […]