如果函数可以接受可变数量的参数,则该函数是可变参数;也就是说,它的arity并不固定。缩写“varargs”通常用于指代这些类型的函数。
我对 功能的使用有点困惑。我不知道如何正确地将 va_list 传递给参数函数。这是我想要实现的目标的一个简化示例: #
假设我们有一个可变参数函数,如下所示: def foo(*args, **kwargs): 经过 我想编辑 foo,以便它打印参数列表。例如,我们想要以下
fcntl 被定义为可变参数函数 int fcntl(int fd, int action, ...) ,有时采用 int arg,有时采用 void* arg。 我想为这个 libc 函数编写一个日志拦截器(我们...
最近我遇到了一种情况,在java中使用varargs是合乎逻辑的。然后我发现可变参数只是数组的语法糖,并且很好奇它对性能的影响
设计具有可变参数长度的(高性能)方法时,例如 无效消耗(T t1) 无效消耗(T t1, T t2) 无效消耗(T t1,T t2,T t3) a) 另一个 ov...
我有一个类,有两个这样的方法: 公共课假人{ 公共无效 doIt(字符串 arg1,文件 arg2,作家... ctx){ // 做一些非常重要的事情... } 公共无效 doIt(字符串 arg1,
我一直在尝试编译flann,但出现了这个错误! ''va_list' 尚未声明' 任何人都可以帮我解决这个错误吗? 如果可以的话,请告诉我这么简单,我真的是编程新手! ...
我想注释一个将多个迭代器或生成器组合成一个的函数,两个迭代器的情况很简单: def merge_two_iterators[T, H]( gen1: 迭代器[T], 第二代:迭代器...
我目前正在开发一个 Swift 项目,并在尝试将可变参数从一个函数传递到另一个函数时遇到问题。 具体来说,我期望我可以直接通过vari...
我可以将对象数组作为 C# 中 params 方法的多个参数传递吗?
例如我有这样的 C# 方法: void someMethod(String arg1, params object[] extras) { foreach(额外对象中的额外对象) { Console.WriteLine(额外); } } 当我称其为l...
typescript - 无法传递与其参数类型相同的函数参数
这是演示该问题的基本版本。有谁知道为什么我无法将返回值传递给包装函数? javascript 可以工作,但 typescript 不允许。 // 接受
我在使用我编写的可变参数 printf 样式函数时遇到了一些麻烦,该函数在没有可变参数时可以正常工作,但在有可变参数时则无法正常工作,例如: do_print("测试名称", &...
我有一个函数 func more(... t)。我想知道是否可以使用切片来填充参数列表......。 我正在尝试解决以下程序。基本上是模仿正常的外壳...
如果我有一个 va_list 我知道如何提取它的所有元素: 无效 printInts(int n,...) { va_列表 va; va_start(va,n); for(无符号整数 i=0; i 如果我有一个 va_list 我知道如何提取它的所有元素: void printInts(int n,...) { va_list va; va_start(va, n); for(unsigned int i=0; i<n; i++) { int arg=va_arg(va, int); printf("%d",arg); } va_end(va); } 因此,当我调用 printInts(3,1,2,3) 时,va_list 会填充所有参数。 但是如何在不使用 va_start 的情况下手动填充 va_list 呢?我的意思是我想要类似的东西: va_list va; push_arg(va, int, 5); // And so on until I fill all parameters ... 我需要这个,因为有一个函数接受 va_list 作为参数,但我不知道如何填充该 va_list 的所有参数。 无法显式填充 va_list。 您应该编写一个包装函数。假设您需要调用函数 foo,而不是手动填写 va_list,而是定义一个新函数,如下所示: void call_foo(int arg1, ...) { va_list ap; va_start(ap, arg1); foo(arg1, ap); va_end(ap); } 现在你可以调用 foo,它需要一个 va_list,无论你喜欢什么,例如: call_foo(1,2,3,4);, call_foo(1, 1, "你好");等等 这仅允许您在编译时指定参数,无法在运行时构建参数。 通常,这些功能是成对出现的。如果您有“va-accepting”功能,则很容易创建另一个功能: void printInts_v(int n, va_list ap) { unsigned int i=0; for(i=0; i<n; i++) { int arg=va_arg(ap, int); printf("%d", arg); } } 这个函数可以这样调用: void printInts(int n,...) { va_list ap; va_start(ap, n); printInts_v(n, ap); va_end(va); } 但我认为没有办法可以便携式地预先填充va_list以供以后使用。 如果您致力于一种架构并且可移植性不是问题,那么您可以自己制作一些东西。具体如何做到这一点是特定于平台的。 我认为没有标准化的方法可以做到这一点。另一方面,这样的预填充 va_list 是非常无用的,因为也无法“查询”它的可用参数的数量和类型。 由于其他回复表明这是不可能的(这将是在下一版本的语言设计中添加它的一个很好的理由),唯一可移植的可能性是 检查两次文档以调查您是否没有错过或 误解了您尝试使用的框架:我 有完全相同的问题here,它出现在答案中 我没有使用正确的调用来完成我想做的事情; 自己编写一个函数,该函数将指针数组而不是 va_list 作为参数,并将问题分解为多次调用(并不总是可能);或 假设您尝试使用的框架设计不佳...... 将函数拆分为多个调用适用于 printf 系列 - Kernighan & Ritchie 中有相关代码,大致如下: void printf_OclFile(struct OclFile* self, char* f, void* sq[]) { int n = length(sq); if (n == 0 || self->actualFile == NULL) { return; } void* ap; char* p = f; int i = 0; char* sval; int ival; double dval; ap = sq[0]; for ( ; *p != '\0' && i < n; p++) { if (*p != '%') { char* p0 = subString(p,1,1); fputs(p0, self->actualFile); continue; } p++; /* Points to flag after % */ switch (*p) { case 'd' : ival = *((int*) sq[i]); i++; fprintf(self->actualFile, "%d", ival); break; case 'f' : dval = *((double*) sq[i]); i++; fprintf(self->actualFile, "%f", dval); break; case 's' : sval = ((char*) sq[i]); i++; fprintf(self->actualFile, "%s", sval); break; default : char* p0 = subString(p,1,1); fputs(p0, self->actualFile); break; } } } 正如这里许多人所说:没有标准 API 可以将数据添加到 va_list,尤其是逐一添加数据。但有一些解决方法可能适合某些情况。 此外va_list在不同平台上有不同的实现。这意味着即使您对实现进行逆向工程,也不能保证这在将来会起作用,因为实现可能只是改变。为了使代码在其他平台上使用该方法 - 有必要重复逆向工程。 填写va_list的标准方法是使用具有可变参数数量的函数。会有限制 - 不可能一一添加参数,但如果我们知道可以添加的参数有最大数量,则可能可以创建 if/else (生成代码)这将覆盖可能的范围。另外,请记住,这种方法使用堆栈,而 C 语言的堆栈相当有限。这种方法的另一个挑战是 - va_list 仅在具有可变参数的函数范围内工作,并且将 va_list 取出很棘手。这是一个片段(仅用于教育目的,请勿将其用于生产),它可以完成这项工作(在 Linux、Macos 和 Windows mingw 上测试): /** @brief the cross-platform way to pass va_list back and forth in functions */ struct va_list_container { va_list parameters; }; // this must be big enough to cover stack for alloca #define _va_list_padding (int)0x5555, (int)0x5555, (int)0x5555, (int)0x5555 static inline void va_list_container_start(void** pp, struct va_list_container * p, ...) { *pp = (void*)&(pp); // store the top stack param addr va_start(p->parameters, p); } /** @brief wrapper macro to put some things into va_list example how to get va_list using all this combination of macroses WITH_VA_LIST_CONTAINER(c, VA_LIST_CONTAINER(c, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); vsnprintf(buf, sizeof(buf), "%d %d %d %d %d %d %d %d %d %d", c.parameters)); it outputs 1 2 3 4 5 6 7 8 9 10 WARNING: even though it works here - there is no guarantee that it will work everywhere and with everything Try not to use it. Reason: A va_list is intrinsically linked to a specific function call's stack frame. Creating a container to hold it doesn't change this fundamental characteristic. Accessing it in a different function would involve undefined behavior due to potential stack frame changes. */ #define WITH_VA_LIST_CONTAINER(_name_, _in_...) do { \ void* pp = NULL; \ struct va_list_container _name_; \ _in_; \ va_end(_name_.parameters); \ }while(0) /** @brief macro to get va_list from container and protect it with alloca * alternativly we could use 2 alloca - first is to get the original stack addr * and second is to cover pp value (which is the top of the used by va_list_container_start stack) * this will be more precise */ #define VA_LIST_CONTAINER(_name_, _args_...) ({ \ va_list_container_start(&pp, &_name_, _args_, _va_list_padding); \ alloca(((char*)&pp)-((char*)pp)); \ &_name_; \ }) #define VA_LIST_FROM_CONTAINER(_name_, _args_...) VA_LIST_CONTAINER(_name_, _args_)->parameters 现在为了制作 if/else,我们可以做类似的事情(开关部分可以生成为宏): WITH_VA_LIST_CONTAINER(c, switch(num){ case 1: VA_LIST_CONTAINER(c, <val1>); break; case 2: VA_LIST_CONTAINER(c, <val1>, <val2>); break; ... } // now we can use va_list stored in c.parameters, e.g. // if (num == 10) { // vsnprintf(buf, sizeof(buf), "%d %d %d %d %d %d %d %d %d %d", c.parameters)); // } );
我有以下功能用于记录目的: void LogE(const char* 范围, const char* s, ...) { fprintf(stderr, "%s : ", 范围); va_list 列表; va_start(列表,s); vf...
在类型化 Python 中,如何键入您希望传递给另一个更高种类函数的参数的 *args 列表? 例如,这个函数接受一个函数及其第一个参数......
我有一个函数指针和参数,我想保存这些并可能修改它们并用它们调用函数。 我已经看到了部分答案,但我不确定如何完整
最近我想实现一个 printf 包装器。经过一番搜索,我发现 vprintf 很适合这种需求: void my_printf(const char *fmt, ...) { va_list 参数; va_start(参数,fmt);
我遇到了一个函数定义,例如: 字符* abc(字符 *f, ...) { } 三个点是什么意思?
我有一个方法 公共布尔findANDsetText(字符串描述,字符串...额外){ 在里面我想调用另一个方法并传递它额外的内容,但我想向 ex 添加新元素(描述)...