我的博客:www.shishangguan.net
宏定义分为两种:

1.变量式宏定义,如

#define abc  def
#define str "string"
#define num 100

2.函数式宏定义,

#define device_init_wakeup(dev,val) \
do { \
device_can_wakeup(dev) = !!(val); \
device_set_wakeup_enable(dev,val); \
} while()

注意:多行的时候,需要用do{}while(0)包装起来,这样更像一个函数调用。同时注意带有字增自减运算符的情况。

在函数式宏定义中, # 运算符用于创建字符串, # 运算符后面应该跟一个形参(中间可以有空格
或Tab),例如:

#define STR(s) # s
STR(hello world) //展开后为"hello world",自动加双引号。

注意:实参中的多个空格会被替换成一个空格。如果游爽引号",会被自动添加转义符,

## 运算符把前后两个预处理Token连接成一个预处理Token,函数式宏定义和变量式宏定义都可以使用。

#define CONCAT(a, b) a##b
CONCAT(con, cat) //展开后是concat #define HASH_HASH # ## # //展开后是##

函数式宏定义也可使用可变参数,如

#define showlist(...) printf(#__VA_ARGS__)
#define report(test, ...) ((test)?printf(#test):\
printf(__VA_ARGS__))
showlist(The first, second, and third items.);
report(x>y, "x is %d but y is %d", x, y);

替换后变成

printf("The first, second, and third items.");
((x>y)?printf("x>y"): printf("x is %d but y is %d", x, y));

注意,__VA_ARGS__包含参数间的逗号。

还有一种gcc的扩展,如

#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)

,##放在这儿,如果可变参数部分为空的时候,展开的时候第一个参数后不会有逗号。如

DEBUGP("info") //printk("info")

宏展开规则:

1.在展开当前宏函数时,如果形参有#(字符串化操作)或##(记号连接操作)则不进行宏参数的展开,否则先展开宏参数,再展开当前宏(就像先计算函数中的参数,然后调用函数一样)。

2.宏展开不能递归展开。

我的博客:www.while0.com

C语言中的宏总结的更多相关文章

  1. C语言学习笔记--C语言中的宏定义

    1. C 语言中的宏定义 (1)#define 是预处理器处理的单元实体之一(因此,预处理器只是简单的进行替换,并不(2)#define 定义的宏可以出现在程序的任意位置(包括函数体的内部)(3)#d ...

  2. C语言中的宏定义

    目录(?)[-] 简单宏定义 带参数的宏 运算符 运算符 宏的通用属性 宏定义中圆括号 创建较长的宏 较长的宏中的逗号运算符 宏定义中的do-while循环do 空操作的定义 预定义宏 C语言中常用的 ...

  3. C语言中的宏

    写好C语言,漂亮的宏定义很重要,使用宏定义可以防止出错,提高可移植性,可读性,方便性 等等.下面列举一些成熟软件中常用得宏定义...... 1,防止一个头文件被重复包含 #ifndef COMDEF_ ...

  4. 20个C语言中常用宏定义总结

    01: 防止一个头文件被重复包含 #ifndef COMDEF_H#define COMDEF_H//头文件内容#endif 02: 重新定义一些类型防止由于各种平台和编译器的不同,而产生的类型字节数 ...

  5. C语言中的宏展开

    #include<stdio.h> #define f(a,b) a##b #define g(a) #a #define h(a) g(a) int main() { printf(,) ...

  6. c语言中使用宏,需要注意的的几点

    使用#define来定义一些宏,进行一些简洁的替换甚至一些带参数的宏,在linux c代码中很常见,说明它很好.很有用, 但是它也有一些复杂的规矩和陷阱需要注意,下面我记录一些,仅供参考. 1.当使用 ...

  7. C\C++语言中的宏多重展开和递归展开

    宏定义中的#,## 1. 宏中的参数前面使用一个#,预处理器会把这个参数转换为一个字符数组     2.记号粘贴操作符(token paste operator): ##            “## ...

  8. Visual Studio属性配置中使用宏

    在学习C语言的时候,我们曾经遇到过一个宏的概念.宏的作用机理本质上是宏的展开,C语言中的宏的用法也有很多种(水其实很深...),不过从感觉上来讲,人们大致上会在以下的场景中,利用宏来解决一些窘境:一是 ...

  9. 哨兵查找法(明解c语言) + 函数式宏

    //哨兵法,就是将待查找的元素加入待查找的数组的后面,这样可以提高性能(在数据量很庞大的时候体现出来) #include <stdio.h> #define FAILURE -1 //使用 ...

随机推荐

  1. [转]如何学好windows c++编程 学习精髓(收集,整理)

    以下是很多VC爱好者的学习经历,希望对大家有所帮助: 我记得我在网上是这么说的:先学win32的SDK,也就是API, 再学MFC,这么一来呢,就先有个基础,MFC是API的封装, 如果API用的熟了 ...

  2. OpenID说明

    OpenID使用手册 摘要: OpenID是一种开放.离散式的用于用户数字标识的开源框架.在网络应用日益充斥的今天,作为终端用户的我们不得不在每个网站上设置帐号,并管理众多的帐号.而采用OpenID技 ...

  3. HW--自守数

    package testcase; import huawei.Demo; import junit.framework.TestCase;//加入测试框架,不需要写Main函数 public cla ...

  4. 第二篇、C_递归算法

    简介: 在实际应用当中,我们常常会接触到一些递归的数法. 递归算法的特点 递归算法是一种直接或者间接地调用自身算法的过程.在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简 ...

  5. html19-----视频,音乐的插入

    视频格式 MP4 格式是一种新的即将普及的因特网视频格式.HTML5 .Flash 播放器以及优酷等视频网站均支持它. 格式 文件 描述 AVI .avi AVI (Audio Video Inter ...

  6. intellij idea社区版 & maven & git & tomcat/jetty 的struts2项目的搭建

    1.新建一个project,并在project下新建一个maven module.

  7. leetcode Largest Rectangle in Histogram 单调栈

    作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4052343.html 题目链接 leetcode Largest Rectangle in ...

  8. jquery <li>标签 隔若干行 加空白或者加虚线

    $(function () { $('ul li').addClass(function (i) { return i % 6 == 5 ? "ab" : "" ...

  9. 不使用border-radius,实现一个可复用的高度和宽度都自适应的圆角矩形

    现在css3支持圆角矩形,但是为了兼容性问题,虽然比较麻烦,但还是有必要了解一下以下方法. 在一个div内,包含8个div,控制这个8个div的height.margin以及border属性值,以达到 ...

  10. java 中的 & | ~ ^ 运算符分析

    1.与运算符与运算符用符号“&”表示,其使用规律如下:两个操作数中位都为1,结果才为1,否则结果为0,例如下面的程序段.public class data13{public static vo ...