一 、__VA_ARGS__

P454 所讲printf()这些输出函数的参数是可变的,在调试程序时,可能希望定义参数为可变的输出函数,

那么可变参数宏会是一个选择,例如:

#define DEBUG(X, ...) printf("Message", #X,":" __VA_ARGS__)

其中,...表示参数可变,__VA_ARGS__在预处理中为实际的参数集所替换部分。

//variadic.c----可变宏

#define DBG(format, ...) printf("Message"#format":File:%s, Line:%d, Function:%s" __VA_ARGS__,__FILE__, __LINE__ , __FUNCTION__)

int main(void)
{
   double x = 48;
   double y = 0;
   y = sqrt(x);


   DBG(1,"x=%g\r\n",x);
   DBG(2,"x=%.2f,y=%.4f\r\n",x,y);
   return 0;
}

二、若部分不支持__VA_ARGS__,可以采用下面方法

#define DEBUG_BUFFER_MAX_LENGTH 1024
void printDebugMsg( const char* format, ...)
{
    char buffer[DEBUG_BUFFER_MAX_LENGTH + 1]={0};
    va_list arg;
    va_start (arg, format);
    vsnprintf(buffer, DEBUG_BUFFER_MAX_LENGTH, format, arg);
    va_end (arg);
    printf( "%s", buffer );
}

int main(void)
{
   double x = 48;
   double y = 0;
   y = sqrt(x);


   printDebugMsg("x=%g\r\n",x);
   printDebugMsg("x=%.2f,y=%.4f\r\n",x,y);
   return 0;
}
 
 
三、可变参数(P487)
int SqSum(int n1, ...)
{
    va_list arg_ptr;
    int nSqsum = 0;
    int n = n1;
    va_start(arg_ptr,n1);

    while(n > 1)
    {
        nSqsum +=(n*n);
        n = va_arg(arg_ptr,int);
    }

    va_end(arg_ptr);

    return nSqsum;
}

int main(void)
{
    int nSqSum = SqSum(2,3,4,5,-1);
    printf("sqsum = %d\r\n",nSqSum);
    return 0;
}
int SqSum(int n1, ...)参数可以分为两部分:个数确定的固定参数和个数可变的可选参数。函数至少需要一个固定参数,固定参数的声明和普通函数一样;可选参数由于个数不确定,声明时用"…"表示。固定参数和可选参数公同构成一个函数的参数列表。

分析上面例程,来看看各个va_xx的作用:
va_list arg_ptr:定义一个指向个数可变的参数列表指针;
va_start(arg_ptr, argN):使参数列表指针arg_ptr指向函数参数列表中的第一个可选参数,说明:argN是位于第一个可选参数之前的固定参数,(或者说,最后一个固定参数;…之前的一个参数),函数参数列表中参数在内存中的顺序与函数声明时的顺序是一致的。如果有一va函数的声明是void va_test(char a, char b, char c, …),则它的固定参数依次是a,b,c,最后一个固定参数argN为c,因此就是va_start(arg_ptr, c).
 
va_arg(arg_ptr, type):返回参数列表中指针arg_ptr所指的参数,返回类型为type,并使指针arg_ptr指向参数列表中下一个参数。
va_copy(dest, src):dest,src的类型都是va_list,va_copy()用于复制参数列表指针,将dest初始化为src。
va_end(arg_ptr):清空参数列表,并置参数指针arg_ptr无效。
 
说明:指针arg_ptr被置无效后,可以通过调用va_start()、va_copy()恢复arg_ptr。每次调用va_start() / va_copy()后,必须得有相应的va_end()与之匹配。参数指针可以在参数列表中随意地来回移动,但必须在va_start() … va_end()之内。

C Primer Plus(第五版)学习笔记-可变宏:...和__VA_ARGS__的更多相关文章

  1. Primer C++第五版 读书笔记(一)

    Primer C++第五版 读书笔记(一) (如有侵权请通知本人,将第一时间删文) 1.1-2.2 章节 关于C++变量初始化: 初始化不是赋值,初始化的含义是创建变量时赋予其一个初始值,而赋值的含义 ...

  2. C++Primer第五版学习笔记

    <C++ Primer>Learning Note 程序实例下载地址:http://www.informit.com/title/0321714113 第一章            开始 ...

  3. PMBOK(第五版)学习笔记二-十大知识领域(P87)

    五大项目管理过程组:启动.规划.执行.监控.收尾过程组 十大知识领域是:项目整合管理.项目范围管理.项目时间管理.项目成本管理.项目质量管理.项目人力资源管理.项目沟通管理.项目风险管理.项目采购管理 ...

  4. 《C++Primer》第五版习题答案--第三章【学习笔记】

    [C++Primer]第五版[学习笔记]习题解答第三章 ps:答案是个人在学习过程中书写,可能存在错漏之处,仅作参考. 作者:cosefy Date: 2020/1/10 第三章:字符串,向量和数组 ...

  5. 《C++Primer》第五版习题解答--第四章【学习笔记】

    [C++Primer]第五版习题解答--第四章[学习笔记] ps:答案是个人在学习过程中书写,可能存在错漏之处,仅作参考. 作者:cosefy Date: 2020/1/11 第四章:表达式 练习4. ...

  6. 《C++Primer》第五版习题答案--第五章【学习笔记】

    <C++Primer>第五版习题答案--第五章[学习笔记] ps:答案是个人在学习过程中书写,可能存在错漏之处,仅作参考. 作者:cosefy Date: 2020/1/15 第五章:语句 ...

  7. 《C++Primer》第五版习题答案--第六章【学习笔记】

    <C++Primer>第五版习题答案--第六章[学习笔记] ps:答案是个人在学习过程中书写,可能存在错漏之处,仅作参考. 作者:cosefy Date: 2020/1/16 第六章:函数 ...

  8. C++Primer第5版学习笔记(四)

    C++Primer第5版学习笔记(四) 第六章的重难点内容         你可以点击这里回顾第四/五章的内容       第六章是和函数有关的知识,函数就是命名了的代码块,可以处理不同的情况,本章内 ...

  9. C++Primer第5版学习笔记(三)

    C++Primer第5版学习笔记(三) 第四/五章的重难点内容           你可以点击这里回顾第三章内容       因为第五章的内容比较少,因此和第四章的笔记内容合并.       第四章是 ...

随机推荐

  1. Android_listView

    package com.example.app5; import java.util.ArrayList; import java.util.HashMap; import java.util.Lis ...

  2. PV信号量的一些理解

    进程通常分为就绪.运行和阻塞三个工作状态.三种状态在某些条件下可以转换,三者之间的转换关系如下:   进程三个状态之间的转换就是靠PV操作来控制的.PV操作主要就是P操作.V操作和信号量.其中信号量起 ...

  3. 关于Eclipse中的开源框架EMF(Eclipse Modeling Framework),第三部分

    Eclipse Modeling Framework(EMF)中包含了一个开放源代码的工具 JMerge,这个工具可以使代码生成更加灵活,可定制性更好.本文使用一个例子来展示如何将 JMerge 添加 ...

  4. 2013 ACM/ICPC 长沙现场赛 C题 - Collision (ZOJ 3728)

    Collision Time Limit: 2 Seconds      Memory Limit: 65536 KB      Special Judge There's a round medal ...

  5. 浅谈用java解析xml文档(三)

    接上一篇,本文介绍使用JDOM解析xml文档, 首先我们还是应该知道JDOM从何而来,是Breet Mclaughlin和Jason Hunter两大Java高手的创作成果,2000年初, JDOM作 ...

  6. Jquery 实现Xml文件内容处理

    用JS对XMl文件处理实现和用JS处理一般的Dom元素一样; 加载一个Xml内容与新建一个Dom元素基本相同 如: 1.新建一个Dom元素的Jquey语法为:$("<p>hell ...

  7. InvoiceCancelSendApAction

    package nc.ui.pu.m25.action; import java.awt.event.ActionEvent; import nc.bs.framework.common.NCLoca ...

  8. webform处理过程

    一.post/get传值注意几点 post提交的时候,只有写了name属性且没有写disable=true表单元素(input,select,textarea)才会被提交. 如果不确定是get还是po ...

  9. 深入理解java的抽象类和接口(转载)

    原文链接:http://www.cnblogs.com/dolphin0520/p/3811437.html 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的 ...

  10. ASP.NET 4.0 来了

    伴随着VS2010的公开测试,ASP.NET4.0也进入了我们的视线.ASP.NET4.0究竟给我们带来了什么,将在哪些方面提高我们的生产力? 在何时你需要使用ASP.NET4.0开发你的网站程序? ...