论坛摘选(省略参数,va_List,_vsntprintf )等

来源:互联网 发布:mac如何卸载xlplayer 编辑:程序博客网 时间:2024/06/02 12:46

 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);