va_start执行后pArgList指向szFormat后面的第一个可变参数,但没有用va_arg取得其值(包括第二个可变参数),为何可以直接调用_vsntprintf ( szBuffer, sizeof (szBuffer) / sizeof (TCHAR),
szFormat, pArgList)?
你在va_start执行后pArgList的值,即地址已经确定下来了啊
其实在头文件中
typedef char * va_list; //va_list为字符型指针
这么定义的,
而你接下来是要对字符串的处理,做一个输出,所以只要知道一个首地址和长度就可以了
信息已经足够
int _vsnprintf( char *buffer, size_t count, const char *format, va_list argptr );
其中count 为buffer所允许的最大容量
sizeof (szBuffer) / sizeof (TCHAR), //计算最大容量,如果为UNICOLE则sizeof(TCHAR)=2,否则等于0;
------------------------------------------------------------------------------------------------------------------------------------------------------
首地址是已经确认了,是在szFormat之后,长度怎么确定了呢,本例中szFormat后面的不是char *,是两个int 变量cxScreen, cyScreen ,按照定义 pArgList 是va_list,也即是 char * ,是否可以这样理解?
变参函数的 变参数, 就是只提供一个首地址,正如你所说, 长度怎么确定了呢?
如果长度不确定,我又该如何来做呢?
所以就会有格式控制符,体现在这里就是 szFormat, 这也是一个字符串,根据它的内容来解析你的pArgList
常用一点的,比如printf("%s%d", "abc",34);
典型的变参函数,就是通过"%s%d",相当这里的szFormat, 来输出的,
内存里会有一些值,但这些值是什么类型,每个占多少字节,就是有szFormat来控制拉
比如"%s",会找到'/0'止, %d就去找4个字节
不知道你明白了没有
-------------------------------------------------------------------------------------------------------------------------------------------------
哦,明白了,是否可以这样说,只要有格式控制 ,就可以不用va_arg啦,
有那么点意思
看问题要看本质
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
你可以看到va_arg就是通过格式控制来实现的
所以如果你自己提供了格式控制,就不需要它来做了
---------------------------------------------------------------------------------------------------------------------------------------------------
变参函数的核心不是格式,这个仅仅是变参的使用。
可变参数是在直接操纵栈,只要你有办法把你的栈里面的内容通知变参函数,就可以实现可变参数的功能。标准库的printf函数族利用了变参函数来实现格式化的输出,但这个仅仅是变参函数的一种使用方法而已。早期(K&R时期)的printf函数族并没有以...来声明printf的原型,而是把括号留空,利用某些trick来完成这项工作。到了C标准化以后,出现了...作为变参的用法,此时printf的原型就成了
int printf(const char*, ...);
提供了对格式类型的检查(譬如你这样调用printf:printf(1); 这样就不被允许了,但是早期的printf是可以这么干的)
给你个可变参数的例子吧……
#include <stdio.h>
void func(int argc, ...)
//argc保存了参数的个数
//...里面是参数
{
int i, *ptr = &argc + 1;
for(i = 0; i < argc; i++)
{
printf("%d/n", ptr[i]);
}
}
int main(int argc, char* argv[])
{
func(2, 3, 4);
}
以上代码通过gcc 3.4.2的编译……
另外顺带说一句,gcc里面-Wformat可以通知gcc对printf函数族进行完整的类型检查(编译器会解析你给出的格式化字符串),如下代码就会被检测到有问题
int i;
printf("%s", i);