Tag: 可变参数函数

为什么某些库例程同时实现为宏? 为什么“va_arg”宏被声明为一个函数(没有“#define”)?

我正在努力用语言清楚地表达出来。 所以让我把它分成几部分。 背景来自Mike Banahan的C书(链接在下面的每个部分提供)。 这是我的问题,作为粗体的要点: 为什么某些库函数同时也实现为宏? 有什么需要? 这是我从书中读到的内容(第9.1.1节) : 最后一点是,许多库例程可以实现为宏,前提是副作用没有问题(如第7章所述)。 标准保证,如果函数通常作为宏实现,则还将提供用于执行相同作业的真实函数。 要使用真实函数,可以使用#undef取消定义宏名称,或将其名称括在括号中,这样可以确保它不会被视为宏: 我们知道, va_start是一个函数还是宏? 书中的以下文字是混乱的根源,因为它暗示着相同的气息,相邻的线条! (第9.9节) 在尝试访问变量参数列表之前,必须调用va_start 。 它被定义为 #include void va_start(va_list ap, parmN); va_start宏初始化ap以供函数va_arg和va_end随后使用。 最后,最令人困惑的部分。 在下面一行中,清楚地写明了va_arg是一个宏,并继续展示它是如何实现的。 但是如何在没有#define关键字的情况下实现宏,并且返回类型(’type’)也是如此,就好像它是一个函数一样? (第9.9节) 初始化后,可以通过va_arg宏顺序访问提供的参数。 这很奇怪,因为返回的类型由宏的参数决定。 请注意,这不可能作为真正的函数实现,仅作为宏。 它被定义为 #include type va_arg(va_list ap, type); 非常感谢您的回答。 谢谢。

va_arg 64位问题

我有这样的C代码。 在64位Linux系统上,结果是:4294967264而不是-32。 clang和gcc都生成具有相同错误结果的二进制文件。 行中的问题: * v = va_arg(args,long); #include #include #include void setter(long *v, …) { va_list args; va_start(args, v); *v = va_arg(args, long); va_end(args); } int main() { long v = 0; setter((long *) &v, -32); printf(“%ld\n”, v); return 0; }

C中va_list可能存在缓冲区溢出漏洞?

我有以下代码: int ircsocket_print(char *message, …) { char buffer[512]; int iError; va_list va; va_start(va, message); vsprintf(buffer, message, va); va_end(va); send(ircsocket_connection, buffer, strlen(buffer), 0); return 1; } 我想知道这个代码是否通过向变量列表提供大小> 512的char数组来缓冲溢出? 如果是这样 – 我该如何解决这个问题? 谢谢。

可变函数 – 如何确保参数正确传递

有没有办法(内置或代码模式)来确保可变参数传递正确数量的参数? (显然,这将作为API的一部分包含在内,我可以查看自己的内部代码。) 我正在考虑要求UN32 Magic Number成为传递的最后一个参数,并检查可变参数函数的有效性。 有没有人对此有任何想法?

用户在运行时动态输入多个输入

如何在运行时通过c中的用户选择获取多个整数输入。 这里输入的第一行是测试用例的数量。 然后我在这种情况下计算输入数字的总和。 测试用例: 输入 3 1 6 7 2 7 3 4 2 1 输出: 14 16 3 我们可以用这种方式修改 scanf(),以便它可以处理这个动态输入。 我不能将该行作为字符串输入,然后将它们分成数字。 我们可以使用空格和\ n来决定数字,就像我们将字符串作为输入一样作为例子: scanf(“%[^\n]”,&str);

C / C ++ va_list没有正确返回参数

我在使用va_list时遇到问题。 以下代码适用于int: main() { int f1=1; float** m = function(n,f1); } float** function(int n,…) { va_list mem_list; va_start(mem_list, n); for (int i=0;i<n;i++) { for (int j=0;j<n;j++) { //m[i][j]=va_arg(mem_list,float); int f = va_arg(mem_list,int); printf("%i \n",f); } } va_end(mem_list); return NULL; } 但是,当我改为浮动即 float f1=1.0; float f = va_arg(mem_list,float); printf(“%f \n”,f); 它不返回正确的值(值为0.00000)。 我对发生的事情感到非常困惑。

最后命名参数不是函数还是数组?

这个问题是关于vararg函数,以及省略号之前的最后一个命名参数: void f(Type paramN, …) { va_list ap; va_start(ap, paramN); va_end(ap); } 我正在阅读C标准,并发现va_start宏的以下限制: 参数parmN是函数定义中变量参数列表中最右边参数的标识符(恰好在……之前)。 如果使用寄存器存储类,函数或数组类型声明参数parmN,或者使用与应用默认参数提升后生成的类型不兼容的类型,则行为未定义。 我想知道为什么以下代码的行为未定义 void f(int paramN[], …) { va_list ap; va_start(ap, paramN); va_end(ap); } 以下内容并未定义 void f(int *paramN, …) { va_list ap; va_start(ap, paramN); va_end(ap); } 宏可以通过纯C代码实现。 但纯C代码无法确定paramN是否被声明为数组或指针。 在这两种情况下,参数的类型都被调整为指针。 function类型参数也是如此。 我想知道:这个限制的理由是什么? 当内部进行这些参数调整时,某些编译器是否存在实现此问题的问题? (C ++也说明了相同的未定义行为 – 所以我的问题是关于C ++的问题)。

循环通过宏Varargs值

如果我定义一些宏: #define foo(args…) ({/*do something*/}) 有没有办法实际循环args而不是传递给另一个函数? 就像是 #define foo(args…) \ { \ for (int i = 0; i < sizeof(args); ++i) { \ /*do something with args[i]*/ \ } \ }

带省略号的函数原型

我想知道下面的函数原型是否有效。 编译得很好,但这三个时期有点让我失望,我在Google上找不到类似的东西。 void foo(int, …); 谢谢!

使用另一个可变参数函数的未命名参数调用可变参数函数

我有两个可变函数作为foo(format, …)和bar(format, …) 。 我想实现函数foo以便它可以使用相同的参数列表调用bar 。 那是, foo(format…) { … bar(format, …); } 例如,调用foo(“(ii)”, 1, 2)将调用具有相同参数bar(“(ii)”, 1, 2) 。 该foo函数应如何实现? PS:functionbar来自遗留库,我无法更改其界面。