1.要在函数中使用参数,首先要包含头文件<stdarg.h>。
这个头文件声明了一个va_list类型,定义了四个宏,用来遍历可变参数列表。
void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_end(va_list ap);
void va_copy(va_list dest, va_list src);
下面详细介绍这些宏定义:
2.void va_start(va_list ap, last)
va_start必须第一个调用,它初始化va_list类型的变量ap,使ap指向第一个可选参数。参数 last 是可变参数列表(即函数原型中的省略号…)的前一个参数的名字,也就是最后类型已确定的函数参数名。因为这个参数的地址将会被宏va_start用到,所以最好不要是寄存器变量,函数,或者数组。
对于有可变长参数,但是在可变长参数前没有任何的固定参数的函数,如int func (...)是不允许的。 这是ANSI C所要求的,变参函数在...之前至少得有一个固定参数。这个参
数将被传递给va_start(),然后用va_arg()和va_end()来确定所有实际调用时可变长参数的类型和值。
type va_arg(va_list ap, type)
宏va_arg展开后是关于下一个参数的类型和值的表达式,参数type是明确的类型名。
va_arg返回参数列表中的当前参数并使ap指向参数列表中的下一个参数。
void va_end(va_list ap)
每次调用va_start就必须相应的调用va_end销毁变量ap,即将指针ap置为NULL。
void va_copy(va_list dest, va_list src)
复制va_list类型的变量。
每次调用va_copy,也必须有相应的va_end调用。
调用者在实际调用参数个数可变的函数时,要通过一定的方法指明实际参数的个数,例如把最后一个参数置为空字符串(系统调用execl()就是这样的)、-1或其他的方式(函数
printf()就是通过第一个参数,即输出格式的定义来确定实际参数的个数的)。
3. 举例:
#include <iostream.h>
#include <stdarg.h>
int main()
{
int a,b,c,d,e;
int max(int,int...);
cin>>a>>b>>c>>d>>e;
cout<<"The bigger between a and b is "<<max(2,a,b)<<endl;
cout<<"The bigger in the five number is "<<max(5,a,b,c,d,e)<<endl;
return 0;
}
int max(int num,int integer...)
{
va_list ap;
int m=integer;
va_start(ap,integer);
for(int i=1;i<num;i++)
{ int t=va_arg(ap,int);
if (t>m) m=t;
cout<<i<<endl;
}
va_end(ap);
return m;
}
附:MTK中dbg_print函数的实现:
void dbg_print(char *fmt,...)
{
va_list ap;
double dval;
int ival;
char *p, *sval;
char *bp, cval;
int fract;
unsigned short len;
char buffer[1000];
memset(buffer,0,1000);
bp= buffer;
*bp= 0;
va_start (ap, fmt);
for (p= fmt; *p; p++)
{
if (*p != '%')
{
*bp++= *p;
continue;
}
switch (*++p) {
case 'd':
ival= va_arg(ap, int);
if (ival < 0){
*bp++= '-';
ival= -ival;
}
itoa (&bp, ival, 10);
break;
case 'o':
ival= va_arg(ap, int);
if (ival < 0){
*bp++= '-';
ival= -ival;
}
*bp++= '0';
itoa (&bp, ival, 8);
break;
case 'x':
ival= va_arg(ap, int);
if (ival < 0){
*bp++= '-';
ival= -ival;
}
*bp++= '0';
*bp++= 'x';
itoa (&bp, ival, 16);
break;
case 'c':
cval= va_arg(ap, int);
*bp++= cval;
break;
case 'f':
dval= va_arg(ap, double);
if (dval < 0){
*bp++= '-';
dval= -dval;
}
if (dval >= 1.0)
itoa (&bp, (int)dval, 10);
else
*bp++= '0';
*bp++= '.';
fract= (int)(dval- (double)(int)dval);
itof(&bp, fract);
break;
case 's':
for (sval = va_arg(ap, char *) ; *sval ; sval++ )
*bp++= *sval;
break;
}
}
*bp= 0;
// printf(buffer);这里已经得到了我们想要输出的整个字符串的内容
va_end (ap);
}
http://blog.csdn.net/zhuzhubin/archive/2009/03/05/3959034.aspx
#ifndef DBG_PRINTF(_x_)
#ifdef WEBDBG
#define DBG_PRINTF(_x_) /
do{ /
printf("%s(%d)--:",__FILE__,__LINE__);/
printf _x_; /
}while(0);
#else
#define DBG_PRINTF(_x_)
#endif
#endif
__FILE__ 是内置宏 代表源文件的文件名
__LINE__ 是内置宏,代表该行代码的所在行号
/ 是行连接符,会将下一行和前一行连接成为一行,即将物理上的两行连接成逻辑上的一行
#define DBG_PRINTF(_x_) /
do{ /
printf("%s(%d)--:",__FILE__,__LINE__);/
printf _x_; /
}while(0);
这样更方便阅读
-----------------------------------------------------------------------------
http://topic.csdn.net/u/20090513/21/a99a7e94-30cf-47ad-845d-d41defbe4eee.html
//获取网卡吞吐率
void run_throughput()
{
FILE *fp = NULL;
char *szLine = NULL;
size_t len = 0;
unsigned long long nEth0In = 0;
unsigned long long nEth0Out = 0;
unsigned long long nEth1In = 0;
unsigned long long nEth1Out = 0;
unsigned long long nouse = 0;
time_t now;
int nSeconds = 0;
fp = fopen("/proc/net/dev", "r");
if( fp == NULL ) {
DBG_print(LOG_ERR, "run_throughput: open /proc/net/dev error");
return;
}
while(!feof(fp)) {
int i = 0;
char *p = NULL;
if(szLine) {
free(szLine);
szLine = NULL;
}
if( getline(&szLine, &len, fp) < 0 ) {
if(feof(fp))
continue;
DBG_print(LOG_ERR, "run_throughput: read /proc/net/dev error");
fclose(fp);
return;
}
//忽略每行开头的空格
p = szLine;
while( *p && (*p==' ') )
p++;
if( strncmp(p, "eth0", strlen("eth0")) == 0 ) {
sscanf(p, "eth0:%Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu",
&nEth0In,&nouse, &nouse, &nouse, &nouse, &nouse, &nouse, &nouse, &nEth0Out );
}
else if( strncmp(p, "eth1", strlen("eth1")) == 0 ) {
sscanf(p, "eth1:%Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu",
&nEth1In, &nouse, &nouse, &nouse, &nouse, &nouse, &nouse, &nouse, &nEth1Out );
break;
}
else
continue;
}
//更新全局变量
pre_eth0_in = eth0_in;
pre_eth0_out = eth0_out;
pre_eth1_in = eth1_in;
pre_eth1_out = eth1_out;
eth0_in = nEth0In;
eth0_out = nEth0Out;
eth1_in = nEth1In;
eth1_out = nEth1Out;
//计算时间间隔
now = time((time_t*)0);
nSeconds = now-pre_time;
pre_time = now;
//计算网卡流速
eth0_in_bps = (int) ( (eth0_in-pre_eth0_in) / nSeconds );
eth0_out_bps = (int) ( (eth0_out-pre_eth0_out) / nSeconds );
eth1_in_bps = (int) ( (eth1_in-pre_eth1_in) / nSeconds );
eth1_out_bps = (int) ( (eth1_out-pre_eth1_out) / nSeconds );
if(szLine)
free(szLine);
if(fp)
fclose(fp);
}
//获取tcp连接数
void run_tcpconn()
{
FILE *fp = NULL;
char *szLine = NULL;
size_t len = 0;
int i;
int nID;
struct TCP_CONN *conn = NULL;
fp = fopen("/proc/net/tcp", "r");
if( fp == NULL ) {
DBG_print(LOG_ERR, "run_tcpconn: open /proc/net/tcp error");
return;
}
conn = tcp_conns;
while(!feof(fp)) {
char *p = NULL;
if(szLine) {
free(szLine);
szLine = NULL;
}
if( getline(&szLine, &len, fp) < 0 ) {
if(feof(fp))
continue;
DBG_print(LOG_ERR, "run_tcpconn: read /proc/net/tcp error");
fclose(fp);
return;
}
p = szLine;
while( *p && (*p==' ') )
p++;
//除sl开头的行,其余每行都是一个tcp连接
if( strncmp(p, "sl", strlen("sl")) ) {
sscanf(p, "%d:%x:%x %x:%x %x",
&nID,
&(conn->local_ip), &(conn->local_port),
&(conn->remote_ip), &(conn->remote_port), &(conn->st) );
conn++;
}
else
continue;
}
conn->st = 0;
conn = tcp_conns;
nTcpConns = 0;
while(conn->st) {
if(conn->st != TCP_LISTEN) {
nTcpConns++;
}
conn++;
}
if(szLine)
free(szLine);
if(fp)
fclose(fp);
}
int job_run()
{
run_cpu();
run_memory();
run_throughput();
run_tcpconn();
char tmp_buffer[256];
LOG_print("%d,%d,%d,%d,%d,%d,%d,%d",
cpu_percent_used,
mem_total, mem_free,
eth0_in_bps, eth0_out_bps,
eth1_in_bps, eth1_out_bps,
nTcpConns );
fpResult = fopen ("/home/statistics", "a+");
fprintf (fpResult, "***********************************************************/n");
fprintf (fpResult, "CPU: %d /%/n/nMemory Total: %d/nMemory Free: %d/nMemory: %d /%/n/neth0 in:%d/neth0 out:%d/n/neth1 in%d/neth1 out%d/n/nTCP Conns%d/n", cpu_percent_used, mem_total, mem_free, mem_percent_used, eth0_in_bps, eth0_out_bps, eth1_in_bps, eth1_out_bps, nTcpConns);
fputs ("###########################################################/n", fpResult);
}
static void sysstat_sync() {
struct tm *tm;
TargetTime = time((time_t*)0);
tm = localtime(&TargetTime);
TargetTime += (60 - tm->tm_sec);
}
//参考cron实现
static void sysstat_sleep() {
int seconds_to_wait;
seconds_to_wait = (int) (TargetTime - time((time_t*)0));
while (seconds_to_wait > 0) {
seconds_to_wait = (int) sleep((unsigned int) seconds_to_wait);
}
}
int main()
{
int nInterval = 60;
time_t now;
fpResult = fopen ("/home/statistics", "a+");
if (!fpResult)
DBG_print(LOG_DEBUG, "open /home/statistics fail !!!/n");
daemon_init();
openlog("RESOURCE", LOG_NDELAY|LOG_CONS|LOG_PID, LOG_USER);
now = time((time_t*)0);
DBG_print(LOG_DEBUG, "start at %s", ctime(&now));
sysstat_sync();
while(1) {
sysstat_sleep();
now = time((time_t*)0);
DBG_print(LOG_DEBUG, "run job at %s", ctime(&now));
job_run();
do{
TargetTime += nInterval;
} while(TargetTime < time((time_t*)0));
}
now = time((time_t*)0);
DBG_print(LOG_DEBUG, "stop at %s", ctime(&now));
closelog();
if (fpResult)
fclose (fpResult);
return 0;
}