c语言深度解剖
作者:陈正冲
此书题目为“深度”解剖,但实际上并不是真正地深入讲解c语言,只是本书讲解的内容都是容易被大家忽略的内容,都是容易出错的内容。
第一章 关键字
1、c语言有32个关键字,sizeof是关键字。
关键字volatile:说明变量在程序执行中可被隐含地改变。
2、变量定义与变量声明的区别:定义创建了对象并为这个对象分配了内存,声明没有分配内存。
3、register变量:请求编译器尽可能将这个变量存于寄存器,尽可能不是绝对。
定义的变量长度不能大于整型的长度;不能用“&”取地址运算符。
3、static作用:1.表示退出一个块后仍然存在的局部变量。
2.表示本文件中定义的全局变量和函数只限于本文件内使用。
4、32位系统上,short为2个byte,int为4个byte,long为4个byte;char为1个byte;float为4个byte,double为8个byte。
不同系统可能不同,可以用sizeof测试出。
5、变量命名规则:1.用英文词,不用拼音;
2.英文词尽量不缩写,必须时做注释;
3.英文词第一个字母大写;
4.变量名用名词性词组,如DataDeletedFromSD,函数名用动词性词组,如DeleteDataFromSD;
5.宏定义、枚举常数、只读变量等全用大写字母命名,用下划线分割单词;
6.标识符命名规范:模块名缩写+_+作用域前缀+数据类型前缀+含义标识+数组/结构后缀;根据项目组规范;
7.记着初始化。
6、if中bool类型变量与0比较:if(bTestFlag)或if(!bTestFlag);
if中float类型变量与0比较:if(fTestVal>=-EPSINON && fTestVal<=EPSINON)//EPSINON为定义好的精度;
if中指针与NULL的比较:if(p==NULL)或if(p!=NUll);
7、break结束本层循环;continue结束本轮循环,进入下一轮循环。
8、函数不指明返回值类型时,返回值类型为int;
故,函数没有返回值时,应指明为void;函数无参数时也应指明为void。如:void fun1(void)。
9、const:constant缩写,readonly。
10、volatile:用它修饰的变量表示可以被某些未知的因素修改,比如os,硬件或其他线程等。遇到此变量,编译器不再做代码优化。
第二章 符号
1、c注释可以出现在任何地方,编译器把注释解释为一个空格。
2、书写注释规则:1.注释“为何做”而不注释“怎么做”;
2.全局变量一定要给出注释;
3.注释的缩进与代码的缩进一致。
3、反斜杠“\”表示续行时,之后不能有空格,下一行开始也不能有空格。
4、1:整型常量,32位系统中占4个byte;
'1':字符常量,32位系统中占1个byte;
"1":字符串常量,32位系统中占2个byte。
5、++,--:不同编译器会计算出不同的结果,使用时测试,尽量不写复杂的这类语句。、
6、运算符的优先级:加括号。
第三章 预处理
1、-1被称为“魔鬼数”,如果程序中要用到-1,尽量写成宏。如:#define ERROR_POWEROFF -1.
2、有时需要定义宏常数时,可以用const代替,const做类型检查,可减少错误的可能。
3、定义一个宏函数,计算两个数的和:#defile SUN(x, y) ( (x)+(y) )
4、#undef:用来撤销已有的宏定义。
5、#error ERROR_MESSAGE:编译器遇到#error就会生成一个编译错误提示信息,并停止编译。
6、#line number ["filename"]:改变当前行数和文件名。
7、#pragma:设定编译器的状态或指示编译器完成一些特定的动作。
8、内存对齐:空间换时间(编译器完成)。
9、宏定义中#的使用:
#define SQR(x) printf("The square of x is %d.\n", ((x)*(x))), 则SOR(8)的输出为:The square of x is 64.
#define SQR(x) printf("The square of "#x" is %d.\n", ((x)*(x))), 则SOR(8)的输出为:The square of 8 is 64.
第四章 指针和数组
1、最通俗的指针定义:
int* p,一个“int*”类型的模子在内存上咔出了4个字节的空间(32位系统),然后把这4个字节的空间命名为p,同时限定这4个字节的空间里只能存储某个内存地址(即使你存入别的任何数据,都将被作为内存地址来处理),而且以这个内存地址开始的连续4个字节的内存中只能存储某个int类型的数据。
2、NULL大写,有些系统也定义了null或Null,一定要写成NULL,便于代码移植。
3、学语言就学语言,要深入学习,不要管编译器,vc也有很多bug。如:
#include
int main(int argc, char* argv[])
{
int a[5];
printf("sizeof(&a) is %d.\n", sizeof(&a));
printf("sizeof(&a[0]) is %d.\n", sizeof(&a[0]));
return 0;
}
vc输出为:sizeof(&a) is 20. --这就是个bug
sizeof(&a[1]) is 4.
同样的程序在unix上gcc编译器的输出为:
sizeof(&a) is 4.
sizeof(&a[1]) is 4.
4、以指针形式和以下标形式访问数组元素,本质是一样的。如:
char* p="abcdef";
char a[]="123456";
printf("%c.\n", *(p+4)); //输出e
printf("%c.\n", p[4]); //输出e
printf("%c.\n", *(a+4)); //输出5
printf("%c.\n", a[4]); //输出5
5、int* p1[10]:指针数组;
int (*p2)[10]:数组指针。---->int(*)[10] p2
6、二级指针:一级指针保存的是数据的地址,二级指针保存的是一级指针的地址。
7、数组参数和指针参数:
c语言中,当一维数组作为函数参数时,编译器总是把它解释成一个指向其首元素首地址的指针。
fun(a[10]);
fun(char* a);
fun(a[]);
不是把指针变量本身传递给函数,而是传递了指针变量的一个拷贝。
8、函数指针
char* (fun*) (char* p1, char* p2)---->char* (*) (char* p1, char* p2) fun
第五章 内存管理
c语言的经典之处与复杂之处。
1、对程序员来说,内存分三类:静态区;栈;堆。
2、常见内存错误:
a、指针没有指向一块合法内存,解决方法:mallac
b、为指针分配的内存太小(注意字符串常量最后的结束符“\0”)
c、内存分配成功,但未初始化(初始化为0,NULL,memset)
d、内存越界(for循环)
e、内存泄漏(没有释放),解决方法:free
f、内存已释放,但又访问指针。
第六章 函数
一些较好的规则:
1、使用空行;
2、缩进用4个空格;
第七章 文件结构
阅读(2298) | 评论(1) | 转发(0) |