1. 语句表达式

GNU C 把包含在括号中的复合语句看做是一个表达式,称作语句表达式,它可以出现在任何允许表达式的地方。我们可以在语句表达式中使用原本只能在复合语句中使用的循环、局部变量等,例如:

#define min_t(type, x, y)   \
({ type _x = (x); type _y = (y); _x < _y ? _x : _y; }) int ia, ib, mini;
float fa, fb, minf; mini = min_t(int, ia, ib);
minf = min_t(float, fa, fb);

因为重新定义了 _x 和 __y 这两个局部变量,所以以上述方式定义人宏将不会有副作用。在标准 C 中,对应的如下宏则会产生副作用:

#define min(x, y) ((x) < (y) ? (x) : (y))

代码 min(++ia, ++ib) 会被展开为 ((++ia) < (++ib) ? (++ia) : (++ib)),传入宏的“参数”被增加 2 次。

2. typeof 关键字

typeof(x) 语句可以获得 x 的类型,因此,我们可以借助 typeof 重新定义 min 这个宏:

#define min(x, y)   ({          \
const typeof(x) _x = (x); \
const typeof(y) _y = (y); \
(void) (&_x == &_y); \
_x < _y ? _x : _y; })

(void) (&_x == &_y) 的作用

我们不需要像 min_t(type, x, y) 这个宏那样把 type 传入,因为通过 typeof(x)、typeof(y) 可以获得 type。代码行 (void)(&_x == &_y) 的作用是检查 _x 和 _y 的类型是否一致。

3. 可变参数宏

标准 C 就支持可变参数函数,意味着函数的参数是不固定,例如 printf() 函数的原型为:

int printf(const char *format [, argument]...);

而在 GNU C 中,宏也可以接受可变数目的参数,例如:

#define per_debug(fmt, arg...)  \
printk(fmt, ##arg)

这里 arg 表示其余的参数,可以是零个或多个,这些参数以及参数之间的逗号构成 arg 的值,在宏扩展时替换 arg,例如下列代码:

pr_debug("%s : %d", filename, line)

会被扩展为:

printk("%s : %d", filename, line)

使用“##”的原因是处理 arg 不代表任何参数的情况,这时候,前面的逗号就变得多余了。使用“##”之后,GNU C 预处理会丢弃前面的逗号。

参考自:《Linux 设备驱动开发》

GNU C 与 ANSI C(下)的更多相关文章

  1. GNU C 、ANSI C、标准C、标准c++区别和联系

    转载自点击打开链接 GNU计划,又称革奴计划,是由Richard Stallman在1983年9月27日公开发起的.它的目标是创建一套完全自由的操作系统.它在编写linux的时候自己制作了一个标准成为 ...

  2. VC 编程ANSI环境下读写Unicode文件

    没有注意到文件编码的不同会产生这么多的问题,在动手以前查询了很多资料,在本博客中收藏了不少先辈的成果,在这里一并表示致敬!       关于ANSI和Unicode编码的原理在这里也不说了,主要讲下如 ...

  3. GNU C 与 ANSI C的区别

    1.零长度数组 GNU C允许使用零长度数组,定义变长度对象时比较方便 struct var_data { int len; char data[0]; }; var_data的大小仅为一个int型, ...

  4. GNU C 与 ANSI C(上)

    Linux 上可用的 C 编译器是 GNU C 编译器,它建立在自由软件基金会的编程许可证的基础上,因此可以自由发布.GNU C 是对标准 C 进行的一系列扩展,以增强标准 C 的功能. 1. 零长度 ...

  5. GNU C与ANSI C的不同

    引用:http://tsroad.lofter.com/post/376316_57ac519 1.GNU C可定义0长度数组,目的是为了定义可变长结构体. struct var_struct{    ...

  6. C11 (GNU Dialect) -std=gnu11 和 -std=c11

    C11 (GNU Dialect) -std=gnu11 和 -std=c11 C11 (GNU Dialect) -std=gnu11 和 -std=c11 用于 IntelliSense 的 C ...

  7. C++对象模型与内存位对齐的简单分析(GNU GCC&VS2015编译器)

    以Fruit和Apple为例进行分析: Fruit和Apple的定义如下: 通过在两种编译环境下的测试(GNU GCC & VS2015),可以发现这两种编译器的对象模型是一样的,如下图所示: ...

  8. linux下阅读源代码的工具

    说来真是惭愧呀.一直在用VIM 做开发.却不知道VI 里还有这么好使的工具.以前一直都是用: find -type f -print | xargs grep -i **** 在源代码里查找. 原来L ...

  9. 有关UNICODE、ANSI字符集和相关字符串操作

    Q UNICODE字符串如何显示 A 如果程序定义了_UNICODE宏直接用 WCHAR *str=L"unicodestring"; TextOut(0,0,str); 否则就需 ...

随机推荐

  1. cordova 问题汇总

    用chrome进行调试: https://jingyan.baidu.com/album/db55b609fde96d4ba30a2fa9.html?picindex=8 http://rensann ...

  2. python 类成员知识点学习的一个坑(初学者,大神请绕行)

    先来段小程序class Foo: name = "abc" def __init__(self,age): self.age = age print(Foo.name)Foo.na ...

  3. POJ3040--Allowance(贪心)

    http://poj.org/problem?id=3040 思路: 输入时,如果有大于c的,直接把数量加到结果中,不把他加到数组中 把钱按面值排序 想取最大面额的钱,保证取到的钱小于等于c 然后取最 ...

  4. 《python语言程序设计》_第6章_函数

    # 6.1_引言 程序1: 结果: Sum from 1 to 10 is 55Sum from 20 to 38 is 513Sum from 35 to 50 is 630 程序2: #程序1和2 ...

  5. app锁定屏幕方向,某一个界面支持屏幕旋转~

    AppDelegate.h 加 @property (nonatomic, assign) BOOL allowRotation; Appdelegate.m加 -(NSUInteger)applic ...

  6. ASP.NET MVC项目实现BasePage基类用作ASPX.CS网页继承

    在ASP.NET MVC项目开发,还是需要创建一些Web Page来实现一些功能,如呈现报表等... 但是一旦项目的.ASPX网页太多了,其中的程序代码也会有代码冗余,出现这些情况,我们得需要对这些代 ...

  7. 包建强的培训课程(13):iOS与ReactNative

    @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...

  8. 【sql注入】浅谈sql注入中的Post注入

    [sql注入]浅谈sql注入中的Post注入 本文来源:i春秋学院 00x01在许多交流群中,我看见很多朋友对于post注入很是迷茫,曾几何,我也是这样,因为我们都被复杂化了,想的太辅助了所以导致现在 ...

  9. 网络编程懒人入门(六):深入浅出,全面理解HTTP协议

    本文引用了自简书作者“涤生_Woo”的文章,内容有删减,感谢原作者的分享. 1.前言 HTTP(全称超文本传输协议,英文全称HyperText Transfer Protocol)是互联网上应用最为广 ...

  10. nginx安装配置并布置网站

    之前做的网站都是用的apache,关于apache和Nginx的区别也不说了,百度上也都有,而且apche和nginx可以共存,这个之后再说. 首先安装nginx,我用的云主机,直接用yum安装 #y ...