GNU C 与 ANSI C(下)
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; })
我们不需要像 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(下)的更多相关文章
- GNU C 、ANSI C、标准C、标准c++区别和联系
转载自点击打开链接 GNU计划,又称革奴计划,是由Richard Stallman在1983年9月27日公开发起的.它的目标是创建一套完全自由的操作系统.它在编写linux的时候自己制作了一个标准成为 ...
- VC 编程ANSI环境下读写Unicode文件
没有注意到文件编码的不同会产生这么多的问题,在动手以前查询了很多资料,在本博客中收藏了不少先辈的成果,在这里一并表示致敬! 关于ANSI和Unicode编码的原理在这里也不说了,主要讲下如 ...
- GNU C 与 ANSI C的区别
1.零长度数组 GNU C允许使用零长度数组,定义变长度对象时比较方便 struct var_data { int len; char data[0]; }; var_data的大小仅为一个int型, ...
- GNU C 与 ANSI C(上)
Linux 上可用的 C 编译器是 GNU C 编译器,它建立在自由软件基金会的编程许可证的基础上,因此可以自由发布.GNU C 是对标准 C 进行的一系列扩展,以增强标准 C 的功能. 1. 零长度 ...
- GNU C与ANSI C的不同
引用:http://tsroad.lofter.com/post/376316_57ac519 1.GNU C可定义0长度数组,目的是为了定义可变长结构体. struct var_struct{ ...
- C11 (GNU Dialect) -std=gnu11 和 -std=c11
C11 (GNU Dialect) -std=gnu11 和 -std=c11 C11 (GNU Dialect) -std=gnu11 和 -std=c11 用于 IntelliSense 的 C ...
- C++对象模型与内存位对齐的简单分析(GNU GCC&VS2015编译器)
以Fruit和Apple为例进行分析: Fruit和Apple的定义如下: 通过在两种编译环境下的测试(GNU GCC & VS2015),可以发现这两种编译器的对象模型是一样的,如下图所示: ...
- linux下阅读源代码的工具
说来真是惭愧呀.一直在用VIM 做开发.却不知道VI 里还有这么好使的工具.以前一直都是用: find -type f -print | xargs grep -i **** 在源代码里查找. 原来L ...
- 有关UNICODE、ANSI字符集和相关字符串操作
Q UNICODE字符串如何显示 A 如果程序定义了_UNICODE宏直接用 WCHAR *str=L"unicodestring"; TextOut(0,0,str); 否则就需 ...
随机推荐
- cordova 问题汇总
用chrome进行调试: https://jingyan.baidu.com/album/db55b609fde96d4ba30a2fa9.html?picindex=8 http://rensann ...
- python 类成员知识点学习的一个坑(初学者,大神请绕行)
先来段小程序class Foo: name = "abc" def __init__(self,age): self.age = age print(Foo.name)Foo.na ...
- POJ3040--Allowance(贪心)
http://poj.org/problem?id=3040 思路: 输入时,如果有大于c的,直接把数量加到结果中,不把他加到数组中 把钱按面值排序 想取最大面额的钱,保证取到的钱小于等于c 然后取最 ...
- 《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 ...
- app锁定屏幕方向,某一个界面支持屏幕旋转~
AppDelegate.h 加 @property (nonatomic, assign) BOOL allowRotation; Appdelegate.m加 -(NSUInteger)applic ...
- ASP.NET MVC项目实现BasePage基类用作ASPX.CS网页继承
在ASP.NET MVC项目开发,还是需要创建一些Web Page来实现一些功能,如呈现报表等... 但是一旦项目的.ASPX网页太多了,其中的程序代码也会有代码冗余,出现这些情况,我们得需要对这些代 ...
- 包建强的培训课程(13):iOS与ReactNative
@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...
- 【sql注入】浅谈sql注入中的Post注入
[sql注入]浅谈sql注入中的Post注入 本文来源:i春秋学院 00x01在许多交流群中,我看见很多朋友对于post注入很是迷茫,曾几何,我也是这样,因为我们都被复杂化了,想的太辅助了所以导致现在 ...
- 网络编程懒人入门(六):深入浅出,全面理解HTTP协议
本文引用了自简书作者“涤生_Woo”的文章,内容有删减,感谢原作者的分享. 1.前言 HTTP(全称超文本传输协议,英文全称HyperText Transfer Protocol)是互联网上应用最为广 ...
- nginx安装配置并布置网站
之前做的网站都是用的apache,关于apache和Nginx的区别也不说了,百度上也都有,而且apche和nginx可以共存,这个之后再说. 首先安装nginx,我用的云主机,直接用yum安装 #y ...