viod func(const char *fmt, ...)
{
printf("%p", &fmt);
}
函数调用:
func("test",1,2,3,4,5,6,7);
这段代码我用GDB查看内存,发现fmt
这个参数临近的内存都没有1、2、3、4、5、6、7这些数字出现。
那么这些参数都去哪里了呢?程序是否单独分配了空间(栈外)存储这些值?如果是的话,该如何找到这个空间呢?
使用gcc-9.1.0
编译
系统版本:CentOS Linux release 7.3.1611 (Core)
鉴于有人可能会推荐我使用stdarg.h
里的va_list
、va_start
、va_arg
、va_end
宏。在此我先谢过。
我的目的是写出一个不需要stdarg.h
头文件的变参函数!
这个参数咋传,跟你用得编译器、操作系统,目标体系结构都有关 ... ,可以去看一下Calling Convetion简单了解一下。
对 gcc Linux x86-64 来说,开始的几个参数根本不在栈里,而是用的寄存器。
把你的函数拼了个程序,放到godbolt上看了一下:
func 的调用是这样:
可以看出除了 6 跟 7 ,其他所有参数都在寄存器里。
进入 func 之后,这些参数又被从寄存器放回了内存(为了实现 va_list 等等 ...):
然而第一个参数跟后续的并不连续,并且参数 5 (后放进内存的)跟 参数 6 (直接压栈)也并不连续。
最后,其他的编译器/操作系统/体系结构的组合,可能完全不是这么搞的。比如 x86(32位) ,所有参数都会被压倒栈里。