zoukankan      html  css  js  c++  java
  • va_list ,va_start ,va_arg ,va_copy ,va_end ,vsprintf ,vsnprintf 详细解析

    1定义

    这些宏在stdarg.h,定义如下:

     1 #include <stdarg.h>  
     2 typedef char *va_list;
     3 #define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )
     4 #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) //第一个可选参数地址
     5 #define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) //下一个参数的值
     6 #define va_end(ap) ( ap = (va_list)0 ) // 将指针置为无效
     7 
     8 void va_start(va_list ap, last);     
     9 type va_arg(va_list ap, type);       
    10 void va_end(va_list ap);   
    11 void va_copy(va_list dest, va_list src);

    以上几个宏定义关键是_INTSIZEOF(n)的含义。

    2 #define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )

    含义是向上取整成 sizeof(int) 的整数倍,用来地址对齐。

    1)  数学整除的例子

    举个简单的数学整除运算例子

    如5/2=2, 7/2=3,再进行如下运算:

    (5/2)*2=4, (7/2)*3=6

    即可得到小于被除数的最大的除数的整数倍。

    2)字节对齐的含义:

    现在有以数据长度为L = 4M+m,如果按照M字节对齐, 对齐后需占用5个M,但实际长度记为4M+m。

     

    如上,蓝色一个格为M字节,红色为m字节,m < M。

    经过上述数学整除运算后L变成4M = (L/M) * M。

    但是与所需的5M 少了一个M。那怎么办呢?

    如果将原数据长度增加一格(L+M),再进行上述运算,即((L+M)/M) * M = 5M

    3)但是呢,会存在如下的问题

    假设数据长度为Y = 6M,刚好为一格长度M的整数倍。

    经过以上运算为:((Y+M)/M) * M = 7M,那如果不加M ,只加M-1呢?

    ((Y+M-1)/M) * M = 6M,对头,这样就完美了。

    4)言归正传,解释宏定义。

    (sizeof(n)+sizeof(int)-1) & (~(sizeof(int) - 1)) = _INTSIZEOF(n)

    ((Y+M-1)                        /M) * M                    = 6M

    &符号左边部分相当于(Y+M-1),右边&~(sizeof(int) - 1),对应/M*M。对二进制来说就是右移M位,再左移M位。因为右移会丢掉低位的,再次左移后相当于把低位清零了。

    若a为2的n次幂,那就是最高位为1,其余位即低位为n个0。

    a-1的二进制相反,低位n个1,最高位为0。再按位取反就是a,即(~(sizeof(int) - 1))。

    最后再按位与,就可以实现将A的低n位清零,即&(~(sizeof(int) - 1))。

    3 函数堆栈中的摆放

    在进程中,堆栈地址是从高到低分配的.当执行一个函数的时候,将参数列表入栈,压入堆栈的高地址部分,然后入栈函数的返回地址,接着入栈函数的执行代码 ,堆栈地址不断递减。最后一个参数在列表中地址最高部分,第一个参数在列表地址的最低部分.参数在堆栈中的分布情况如下:

    最后一个参数

    倒数第二个参数

    ...

    第一个参数

    函数返回地址

    函数代码段

    void va_copy(va_list dest, va_list src);很简单,src copy到 dest,不在详述。

    4实例

    1)int型实例:

     1 #include <stdio.h>
     2 #include <stdarg.h>
     3 //int demo(int format, ...);
     4 int demo(int format, ...)
     5 {
     6   va_list ap;
     7   int n;
     8   va_start(ap, format);
     9   while(n != 0{
    10     n = va_arg(list, int);
    11    // if(n != 0){
    12       printf("%d
    ",n);
    13      // break;
    14    // }
    15     printf("para #%d is:%d ",sum,n);
    16   }
    17   va_end(ap);
    18   return 0;
    19 }
    20 void main()
    21 {
    22   demo(1,2,3,4,5,6,7,8,9,0);
    23 }

    编译执行结果:

     ./test

    para #0 is : 2

    para #0 is : 3

    para #0 is : 4

    para #0 is : 5

    para #0 is : 6

    para #0 is : 7

    para #0 is : 8

    para #0 is : 9

    para #0 is : 0

    2)char型实例:

     1 #include <stdio.h>
     2 #include <stdarg.h>
     3 //int demo(int format, ...);
     4 void demo(char *format, ...)
     5 {
     6   va_list list;
     7   va_start(list,format);
     8   char *ch;
     9   while(ch != ""){
    10     ch = va_arg(list, char *);
    11     //if(strcmp(ch,"") == 0){
    12      printf("%s
    ",ch);
    1314     //}
    15    printf("%s ",ch);
    16   }
    17   va_end(list);
    18 }
    19 int main()
    20 {
    21   demo ("test","this","is","a","test","");
    22   return 0;
    23 }

    编译执行结果:

     ./test

    para #0 is : this

    para #0 is : is

    para #0 is : a

    para #0 is : test

    para #0 is : 

    3)vsprintf ,vsnprintf的使用实例

     1 #include <stdio.h>
     2 #include <stdarg.h>
     3 char buffer1[80] 4 char buffer2[80];
     5 int demo (char *format, ...)
     6 {
     7   va_list ap;
     8   va_start(ap, format);
     9   vsfprintf(buffer1, format,ap);
    10   vsnprintf(buffer2, 17,format, ap);
    11   va_end(ap);
    12   printf("vsprintf:%s 
    ",buffer1);
    13   printf("vsnprintf:%s 
    ",buffer2);
    14   return 0;
    15 }
    16 int main()
    17 {
    18   int num = 30;
    19   float flat = 90.000000;
    20   char c_data [4]= "abc";
    21   demo ("%d %f %s",num,flat,c_data);
    22   printf("sizeof(int):%d,sizeof(float):%d,sizeof(string):%d 
    ",sizeof(int),sizeof(float),sizeof(string));
    23   return 0;
    24 }

    sizeof(int):4,sizeof(float):4,sizeof(string):4

    vsprintf :30 90.000000 abc

    vsnprintf:30 90.000000 abc

    行胜于言,自强不息。
  • 相关阅读:
    生成测试报告unittest、HTMLTestRunner(pytest、allure)
    接口自动化上传视频(python)
    Android手机测试环境搭建
    jmeter性能测试监控
    jmeter多机联合负载
    jenkins+ant+jmeter接口自动化的持续集成
    jmeter+jenkins 配置过程(很详细)
    XSS攻击测试代码
    web安全测试之 xss攻击
    互联网公司--高级测试工程师面试经验分享
  • 原文地址:https://www.cnblogs.com/xinghuo123/p/12862871.html
Copyright © 2011-2022 走看看