1定义
这些宏在stdarg.h,定义如下:
typedef char *va_list;
#define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) //第一个可选参数地址
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) //下一个参数的值
#define va_end(ap) ( ap = (va_list)0 ) // 将指针置为无效
以上几个宏定义关键是_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 函数堆栈中的摆放
在进程中,堆栈地址是从高到低分配的.当执行一个函数的时候,将参数列表入栈,压入堆栈的高地址部分,然后入栈函数的返回地址,接着入栈函数的执行代码 ,堆栈地址不断递减。最后一个参数在列表中地址最高部分,第一个参数在列表地址的最低部分.参数在堆栈中的分布情况如下:
“
最后一个参数
倒数第二个参数
...
第一个参数
函数返回地址
函数代码段
”
4实例
1)int型实例:
#include <stdio.h>
#include <stdarg.h>
int demo(int format, ...);
int demo(int format, ...)
{
va_list ap;
int n;
va_start(ap, format);
while(1){
n = va_arg(list, int);
if(n != 0){
printf("\n");
break;
}
printf("%d ",n);
}
va_end(ap);
return 0;
}
void main()
{
demo(1,2,3,4,5,6,7,8,9,0);
}
编译执行结果:
2)char型实例:
#include <stdio.h>
#include <stdarg.h>
int demo(int format, ...);
void demo(char *format, ...)
{
va_list list;
va_start(list,format);
char *ch;
while(1){
ch = va_arg(list, char *);
if(strcmp(ch,"") == 0){
printf("\n");
break;
}
printf("%s ",ch);
}
va_end(list);
}
int main()
{
demo ("test","this","is","a","test","");
return 0;
}
编译执行结果:
3)和vfprintf、vfnprintf的使用实例
#include <stdio.h>
#include <stdarg.h>
int demo(int format, ...);
char buffer[50];
void demo (char *format, ...)
{
va_list ap;
va_start(ap, format);
fprintf(buffer, "Error: ");
vfprintf(buffer, format, ap);
va_end(ap);
printf(“buffer%s \n”,buffer);
return 0;
}
int main()
{
demo ("","this","is","a","test","");
return 0;
}
编译执行结果: