、定义与声明的区别:定义创建了对象并为对象分配了内存,、register请求编译器尽可能将变量存在CPU寄存器中以提高访问速度,register变量必须为CPU寄存器所能接受的类型,它须是一个单一的值,并且长度<=整型的长度,由于register变量可能不放在内存中,故不可以用”&”、函数前面加static使得函数成为静态函数,它的作用域仅限于本文件中,、case关键字后面只能是整数或字符型的常量或常量表达式。constinta=5;casea://const只读变量,编译出错,://小数,编译出错,caselabeldoesnotreducetoanintegerconstantcase3/2://没有问题,、“跨循环层”的概念本身是说,由外层循环进入内层循环是要重新初始化循环计数器的,包括保存外层循环的计数器和加载内层循环计数器,退出内层的时候再恢复外层循环计数器。把长循环放在里面可以显著减小这些操作的数量,还可以增加cache的命中率。在多重循环中,如果有可能,应当将最长的循环放在最内层,最短的循环放在最外层,以减少CPU跨切循环层的次数。for(i=0;i<50;i++){for(j=0;j<10000;j++){}}效率比下面这个高for(i=0;i<10000;i++){for(j=0;j<50;j++){}}、void指针的算术操作void*pvoid;pvoid++;//ANSI认为是错误的,因为它认为进行算术操作的指针必须知道它所指向的数据类型大小pvoid+=1;//ANSI认为是错误的//但GNU指定void*的算术操作跟char*相同。、const编译器通常不为普通const只读变量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的值,没有了存储与读内存的操作,使得它的效率也很高。例如:#defineM3//宏常量constintN=5;//此时并未将N放入内存中......inti=N;//此时为N分配内存,以后不再分配!intI=M;//预编译期间进行宏替换,分配内存intj=N;//没有内存分配intJ=M;//再进行宏替换,又一次分配内存!const定义的只读变量从汇编的角度来看,只是给出了对应的内存地址,在程序运行过程中只有一份拷贝。#define定义的宏常量在内存中有若干个拷贝。#define宏是在预编译阶段进行替换,而const修饰的只读变量是在编译的时候确定其值怎么看const修饰哪个对象先忽略类型名(编译器解析的时候也是忽略类型名)。看const离哪个近。离谁近就修饰谁。constint*p;//const*p//const修饰*p,p是指针,*p是指针指向的对象,不可变intconst*p;//const*p//const修饰*p,p是指针,*p是指针指向的对象,不可变int*constp;//*constp//const修饰p,p不可变,p指向的对象可变constint*constp;//前一个const修饰*p,后一个const修饰p,、volatile编译器遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问先看看下面的例子:inti=10;intj=i;//(1)语句intk=i;//(2)语句这时候编译器对代码进行优化,因为在(1)(2)两条语句中,i没有被用作左值。这时候编译器认为i的值没有发生改变,所以在(1)语句时从内存中取出i的值赋给j之后,这个值并没有被丢掉,而是在(2)语句时继续用这个值给k赋值。编译器不会生成出汇编代码重新从内存里取i的值,这样提高了效率。但要注意:(1)(2)语句之间i没有被用作左值才行。再看另一个例子:volatileinti=10;intj=i;//(3)语句intk=i;//(4)语句volatile关键字告诉编译器i是随时可能发生变化的,每次使用它的时候必须从内存中取出i的值,因而编译器生成的汇编代码会重新从i的地址处读取数据放在k中。这样看来,如果i是一个寄存器变量或者表示一个端口数据或者是多个线程的共享数据,就容易出错,所以说volatile可以保证对特殊地址的稳定访问。、大部分编译器中,默认情况,enum会转化为intenumColor{GREEN=1,RED}Col故sizeof(Col)=sizeof(int)第2章、、注释int/*...*/i;//编译器会用空格代替原来的注释,这里
C语言深度剖析读书笔记 来自淘豆网m.daumloan.com转载请标明出处.