《c语言深度剖析》学习笔记2
2012-06-19 09:46
169 查看
第二章:符号
2.1 注释>编译器会用空格代替原来的注释;
>嵌套注释:return /*/*/0*/**/1;
2.5
>左移和右移的位数不能大于数据类型的宽度,不能小于0;
>有符号数的右移,如果原符号位是0,则左端补0;否则,补0/1.
2.7.2
>c语言里,每一个符号都应该包含尽可能多的字符。(贪心法)也就是说,编译器将程
序分解成符号的方法是,从左到右一个一个字符地读入,如果该字符可能组成一个符号,
那么再读入下一个字符,判断已经读入的两个字符组成的字符串是否可能是一个符号的组
成部分;如果可能,继续读入下一个字符,重复上述判断,直到读入的字符组成的字符串
已不再可能组成一个有意义的符号。
3.预处理:
>C语言中的预处理指令:
预处理名称 意义 #define 宏定义 #undef 撤销已定义的宏名 #include 使编译程序将另一源程序嵌入到带有#include 的源文件中 #if 如果#if后面的常量表达式为真,则编译它与#endif之间的代码,否则跳过这写代码; #else #else建立另一个选择 #elif #elif命令类似与else if #endif #endif标识一个#if快的结束 #ifdef 条件编译的一种方法 #ifndef 条件编译的一种方法 #line 改变当前行数和文件名称 #line number["filename"] (方括号内可省略) #error 编译程序时,只要遇到#error就会生成一个编译错误提示信息,并停止编译 #pragma 实现时定义的命令,它允许向编译程序传送各种指令
第三章:预处理
3.1 宏定义>const修饰的只读变量不能用来作为定义数组的维数,也不能放在case后。
>反斜杠作为接续符时,在其后面不能再有任何字符。
>用 define 宏定义注释符号:
#define BSC // #define BMC /* #define EMC */ BSC my single-line comment BMC my multi-line comment EMC书上的意思是说:
因为注释先于预处理指令被处理,当这两行被展开成//...或
/*...*/时,注释已处理完毕,此时再出现//...或/*...*/自然错误。
也就是:编译器之处理一次注释符号,一次处理完之后,如果再有注释符号,编译器就不认识了。
我认为:BSC是可以展开成 // 的;BMC也可以展开成 /* ;但 EMC 应该是被注释掉了(因为先处理注释,后处理宏定义),EMC无法展开成 */ .
测试了一下:
#include <stdlib.h> #define BMC /* #include "f2.h" #define EMC */ int main() { f2(); BMC EMC return 0; } //f2.h #include <stdio.h> void f2() { printf("Hello f2()\n"); }编译结果:
#gcc 2_5.c 2_5.c: 在函数‘main’中: 2_5.c:10:7: 错误: ‘EMC’未声明(在此函数内第一次使用) 2_5.c:10:7: 附注: 每个未声明的标识符在其出现的函数内只报告一次 2_5.c:11:3: 错误: expected ‘;’ before ‘return’
说明编译器先将 "/*" 和 "*/"之间的内容替换为空格,然后将BMC替换为 "/*",EMC未声明...
但是为什么不报错 f2 呢?
>用宏定义表达式时,不要吝啬括号!
>宏函数被调用时,是以实参代换形参,而不是"值传值"。
>#define EMPTY //这样的宏定义是可行的,但它的用途是什么呢?
>宏定义中空格的使用:
#define SUM (x) ((x) + (x))编译器认为这是定义了一个宏:SUM, 其代表的是(x) ((x) + (x)).
所以,当程序中出现SUM(3)时,宏展开为(x) ((x) + (x))(3);//自然会出错:x未定义
在使用宏函数的时候,宏函数名与其后的括号之间可以有括号的。SUM(3) 和 SUM (3)的效果是一样的。
3.3 文件包含
>文件包含实际上是宏替换的延伸。
#include <filename> //到系统规定的路径中去获得这个文件 #include "filename" //预处理先在当前目录中查找此文件,若没有找到,再按照系统指定的路径信息,搜索该文件。 #include 是将已经存在的文件的内容嵌入到当前文件中
3.5 #line预处理
用在编译器的编写中。
3.6 #pragma
#pragma 的作用是设定编译器的状态或者指示编译器完成一些特定的动作。
#pragma message("消息文本") 当编译器遇到这条指令时,就在编译输出窗口将消息文本打印出来.
#pragma code_seg(["section-name"[,"section-class"]]) 能够设置程序中函数代码存放的代码段
#pragma once 只要在头文件的最开始加入这条指令就能够保证头文件被编译一次.
#pragma hdrstop 表示与编译头文件到此为止,后面的头文件不进行预编译.
#pragma warning 设置警告信息
>#pragma pack 内存对齐问题
#include <stdio.h> struct TestStruct1 { char c1; short s; //sizeof(short) = 2 char c2; int i; }; int main() { struct TestStruct1 a; printf("c1:%p, s:%p, c2:%p, i:%p.\n", (unsigned int)(void *) &a.c1 - (unsigned int)(void *) &a, (unsigned int)(void *) &a.s - (unsigned int)(void *) &a, (unsigned int)(void *) &a.c2 - (unsigned int)(void *) &a, (unsigned int)(void *) &a.i - (unsigned int)(void *) &a ); return 0; } //output: c1:(nil), s:0x2, c2:0x4, i:0x8.
>为什么会有内存对齐?
(1字节 = 8位, 1字 = 2字节, 1双字 = 2字, 1四字 = 2双字)
字、双字和四字在自然边界(字:偶数地址; 双字:被4整除的地址; 四字:被8整除的地址)上不需要内存对齐。
为了提高陈徐的性能,数据结构尽可能在自然边界上对齐,因为:为了访问未对齐的内存,处理器需要做两次内存的访问;然而,对齐内存的访问仅需要一次访问.
>#pragma pack(n). 编译器将按照n个字节对齐.
(但是,对齐规则是:每个成员按其类型的对齐参数(通常是类型大小) 和 指定参数(n) 中较小的一个对齐; 结构的长度必须为所用过的所有对齐参数的整数倍(不够补零)).
>#pragma pack(),编译器将取消自定义字节对齐方式.
#pragma pack(8) struct TestStruct4 { char a; long b; //sizeof(long) = 4 }; struct TestStruct5 { char c; struct TestStruct4 d; long long e; //sizeof(long long) = 8 }; #pragma pack()
TestStruct4中,a占1个字节,默认按照1字节对齐,而指定对齐参数是8,取最小值:1----a按照1字节对齐。
同理,b按照4字节对齐。sizeof(TestStruct4) = 8.
TestStruct5中,c按照1字节对齐;d是一个结构体,大小为8字节,对于结构体来说,默认对齐方式是它的所有成员使用的对齐参数中最大的一个,所以d按4字节对齐;
e按照8字节对齐。这样,TestStruct5一共占用24个字节.在GCC下,得出的结果是20(20并不是8的倍数)......(参考:/article/7753712.html)
数组的对齐方式按照数组元素类型的默认对齐方式。
3.7 #运算符
#define SQR(x) printf("The square of x is %d.\n", ((x) * (x))); #define SQR(x) printf("The square of "#x" is %d.\n", ((x) * (x)));
3.8 ##运算符
把两个语言符号组合成单个语言符号.
#define XNAME(n) x##n
XNAME(8)将会展开成 x8
。
相关文章推荐
- 《C语言深度剖析》学习笔记
- 《C语言深度剖析》学习笔记二
- 《C语言深度剖析》学习笔记四--指针
- 《C语言深度剖析》学习笔记--------第一章-----关键字
- 《C语言深度剖析》学习笔记五--内存管理
- 《C语言深度剖析》学习笔记六--函数及编码规范
- 《C语言深度剖析》学习笔记----内存管理(1)----内存对齐
- 《C语言深度剖析》学习笔记1
- 《C语言深度剖析》学习笔记----C语言关键字
- 《c语言深度剖析》学习笔记4
- 《C语言深度剖析》学习笔记----内存管理(2)
- 《C语言深度剖析》学习笔记----C语言中的符号
- 学习笔记
- 《Python基础教程(第2版)》学习笔记(三):
- 学习笔记1
- halcon学习笔记——(9)摄像机标定
- 《HTTP权威指南》学习笔记(四)
- 《Effective C++》学习笔记——条款34
- javascript模板引擎之artTemplate 学习笔记
- 学习笔记:Node.js(一)