我有一个棘手的问题,我今天一直在玩,但为此我还没有想出一个优雅的解决方案.
我们知道,表单的函数void func()需要无限多的参数.现在我已经整理了一个非常简单的最小工作代码片段:
#include <stdio.h>
int func()
{
printf("%d, %d, %d, %d\n");
return 0;
}
int func() {
sucks(0 /* Offset */, 1, 2, 3, 4);
}
Run Code Online (Sandbox Code Playgroud)
好的,我们现在可以使用尽可能多的参数调用func().我正在试验的问题是:我们如何正确访问这些论点的内容?printf()函数打印出类似这样的东西......只是为了验证参数是否实际存在:
anonymous@melina:/tmp$ ./a.out
1 2 3 4
Run Code Online (Sandbox Code Playgroud)
所以现在的问题是:上面的代码片段有点hackish.有没有正确的方法来访问这些参数?或者你是否真的要乱用堆栈指针和内联汇编?作为第一次尝试,我考虑将堆栈指针放在函数的开头,例如,
uint64_t sp;
asm( "mov %%rsp, %0" : "=rm" ( sp ));
Run Code Online (Sandbox Code Playgroud)
...并以某种方式使用它,猜测这些参数实际上在哪里(在内存中).但是......到目前为止我没有成功.
有没有正确的方法来访问这些参数?
是.在函数定义中指定参数列表,其中包含函数的类型和标识符.
你可以做"旧式"(不要这样做,不应该在新代码中使用):
int func(a, b, c, d)
int a;
int b;
int c;
int d;
{
printf("%d %d %d %d\n", a, b, c, d);
}
Run Code Online (Sandbox Code Playgroud)
或正常:
int func(int a, int b, int c, int d) {
printf("%d %d %d %d\n", a, b, c, d);
}
Run Code Online (Sandbox Code Playgroud)
或者使用stdarg.h:
int func(int a, ...) {
va_list ap;
va_start(va, a);
int b = va_arg(va, int);
int c = va_arg(va, int);
int d = va_arg(va, int);
printf("%d %d %d %d\n", a, b, c, d);
va_end(ap);
}
Run Code Online (Sandbox Code Playgroud)
或者从第二个arg使用stdarg.h:
int func(int a, int b, ...) {
va_list ap;
va_start(va, b);
int c = va_arg(va, int);
int d = va_arg(va, int);
printf("%d %d %d %d\n", a, b, c, d);
va_end(ap);
}
Run Code Online (Sandbox Code Playgroud)
或者从第三个arg使用stdarg.h:
int func(int a, int b, int c, ...) {
va_list ap;
va_start(va, c);
int d = va_arg(va, int);
printf("%d %d %d %d\n", a, b, c, d);
va_end(ap);
}
Run Code Online (Sandbox Code Playgroud)
stdarg.h需要在参数列表中至少有一个第一个参数被声明.所以没有办法处理带有未指定数量和类型的参数的函数,但是有一个way(stdarg.h)来处理具有至少1个参数的函数,后跟未指定的参数数量和类型.
...形式void的函数
func()占用了无数的参数
这不是真的.我认为没有一种C标准方法可以将无数个参数传递给函数.
表单的功能func()采用未指定的参数数量和类型.它们采用有限数量的参数,但在遇到此类函数声明的事务单元中未指定该数字.如果函数定义有5个参数,则它们采用5个参数,否则为未定义的行为.如果函数定义在这种情况下采用elipsis(,...)no information about the number or types of the parameters after the comma is supplied.(C11 6.7.6.3p9),则不指定参数个数.
或者你是否真的要乱用堆栈指针和内联汇编?
是的,你必须"搞乱"实现定义的行为.
... va_start的ISO实现需要额外的第二个参数.用户应该在这里写出函数的最后一个命名参数.
但是,va_start不应该使用此参数.
您需要指定第二个参数va_start.也许更多关于这样的话题可以在这个主题中找到.
printf("%d%d%d%d \n");
这是未定义的行为.一旦你的程序有不确定的行为,鼻腔恶魔就会开始在你的房间里产卵并争取独立.它可能在您的平台或实现上有明确定义的行为,但这是错误的,它不再是C语言.If there is a "correct" behavior according to your mental model of the language, that model is simply wrong;从这个线程.从语言的角度来看,鼻子恶魔争取独立,程序无效.