2011年 03月 03日 星期四 12:36:51 CST
0.标准头文件的特点:具有幂等性、相互独立性、和文件级别的声明等同。
库中的每一个可见函数都占据着单独的C源文件;
每个隐藏的名字都以一个下划线和一个大写字母开头;
库中隐藏的函数和数据对象通常占据以x开头命名的C源文件;
在一个库的可见函数定义中,函数名被一对括号括住,所有这样的函数声明都会被相应的头文件中的宏定义所掩盖,所以这对括号阻止了翻译程序识别和展开宏。
1. 头文件<assert.h>唯一的目的就是提供宏assert的定义。
2.可以通过在程序的某些地方定义宏NDEBUG来改变assert的展开方式,如果NDEBUG在包含了<assert.h>d的源文件中某处被定义为宏名,那么宏assert就被直接定义为:#define assert(ignore) ((void) 0)
3.宏assert应该作为一个宏而不是一个实际的函数来实现。如果为了访问一个实际函数而禁止宏定义,那么这种行为是未定义的。
4.源文件的名字和源文件的行数分别是预定义的宏_FILE_和_LINE_的值。
5.宏assert没有任何返回值。
6.对<assert.h>来说,每次包含它的时候它的行为都会发生变化。该头文件会改变assert的定义来适应NDEBUG当前的定义状态。
7.要打开断言可以这样写:
#undef NDEBUG
#include <assert.h>
要关闭断言,可以这样写:
#define NDEBUG
#include <assert.h>
8.宏NDEBUG可以重定义,这是良性重定义。
9.宏不能直接调用库的任何输出函数(为了保证库头文件之间的独立性)。
10.一个程序如果不包含某个头文件,就可以定义宏来对该头文件中的任意名字重新命名。
11.宏必须能扩展为一个void类型的表达式。
12.宏应该可以扩展为一个有效并且紧凑的代码。
13.预处理运算符
#(单井号) ——字符串化运算符(后边没有参数时就是空指令,它没有任何作用)
##(双井号) ——连接运算符
#@ ——字符化运算符
14.内置宏__LINE__没有扩展成字符串字面量,它变成了一个十进制常量。把它转换成适当的形式需要一个额外的处理层。那要通过向头文件中添加两个隐藏的宏_STR和_VAL来实现。其中一个宏用它的十进制常量扩展来取代__LINE__,另一个是把十进制常量转化为一个字符串字面量。忽略其中任一个都会得到字符串字面量"__LINE__",而不是你想要的结果。
15.当宏参数是另一个宏的时候 ,需要注意的是凡宏定义里有用'#'或'##'的地方宏参数是不会再展开. (对于理解"_VAL(__LINE__)"是很重要的!!!)
PS:宏_VAL和_STR的命名可以是任意的。
分享到:
相关推荐
B.6 诊断:<assert.h> B.7 变量变元表:<stdarg.h> B.8 非局部跳转:<setjmp.h> B.9 信号处理:<signal.h> B.10 日期与时间函数:<time.h> B.11 由实现定义的限制:<limits.h>和 <float.h> 附录C 变更小结
B.6 诊断:<assert.h> B.7 变量变元表:<stdarg.h> B.8 非局部跳转:<setjmp.h> B.9 信号处理:<signal.h> B.10 日期与时间函数:<time.h> B.11 由实现定义的限制:<limits.h>和 <float.h> 附录C 变更小结
B.6 诊断:<assert.h> B.7 变量变元表:<stdarg.h> B.8 非局部跳转:<setjmp.h> B.9 信号处理:<signal.h> B.10 日期与时间函数:<time.h> B.11 由实现定义的限制:<limits.h>和 <float.h> 附录C 变更小结
B.6 诊断:<assert.h> B.7 变量变元表:<stdarg.h> B.8 非局部跳转:<setjmp.h> B.9 信号处理:<signal.h> B.10 日期与时间函数:<time.h> B.11 由实现定义的限制:<limits.h>和 <float.h> 附录C 变更小结
B.6 诊断:<assert.h> B.7 变量变元表:<stdarg.h> B.8 非局部跳转:<setjmp.h> B.9 信号处理:<signal.h> B.10 日期与时间函数:<time.h> B.11 由实现定义的限制:<limits.h>和 <float.h> 附录C 变更小结
B.6 诊断:<assert.h> B.7 变量变元表:<stdarg.h> B.8 非局部跳转:<setjmp.h> B.9 信号处理:<signal.h> B.10 日期与时间函数:<time.h> B.11 由实现定义的限制:<limits.h>和 <float.h> 附录C 变更小结 ...
#include<stdio.h> main() { FILE *fp; char ch; if((fp=fopen("e10_1.c","rt"))==NULL) { printf("Cannot open file strike any key exit!"); getch(); exit(1); } ch=fgetc(fp); while (ch!=EOF) { putchar(ch); ...
第2章 做一個最簡短的C++程序 2.1 簡單的屏幕輸出小程序 2.2 輸出語句的使用 2.3 std::介紹 2.4 iostream與iostream.h的區別 2.5 重名問題 2.6 註釋 第3章 初步了解函數 3.1 一個簡單的函數 3.2 函數的傳參 3.3 函...
第0章 从零开始 0.1 为什么要用c 0.2 ansi c标准 0.3 从c到c++ 0.4 从c和c++到java 第1章 c语言概述 1.1 编程和预备知识 1.2 程序输出 1.3 变量、表达式和赋值 1.4 使用#define和#include 1.5 使用printf()和scanf...
+-- 第一章 VC入门 |------ 1.1 如何学好VC |------ 1.2 理解Windows消息机制 |------ 1.3 利用Visual C++/MFC开发Windows程序的优势 |------ 1.4 利用MFC进行开发的通用方法介绍 |------ 1.5 MFC中常用类,宏,函数...
1.28 文件中的第一个声明就报出奇怪的语法错误,可我看没什么问题。这是为什么? 1.29 为什么我的编译器不允许我定义大数组,如doublearray[256][256]? 命名空间 1.30如何判断哪些标识符可以使用,哪些被保留了...
1.28 文件中的第一个声明就报出奇怪的语法错误,可我看没什么问题。这是为什么? 15 1.29 为什么我的编译器不允许我定义大数组,如double array[256][256]? 15 命名空间 15 1.30 如何判断哪些标识符可以使用,...