Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2981358
  • 博文数量: 412
  • 博客积分: 3010
  • 博客等级: 中校
  • 技术积分: 7374
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-25 15:15
个人简介

学习是一种信仰。

文章分类

全部博文(412)

文章存档

2014年(108)

2013年(250)

2010年(11)

2009年(43)

我的朋友

分类: C/C++

2009-09-19 10:17:39

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) |
给主人留下些什么吧!~~

chinaunix网友2010-01-03 00:15:33

下载地址http://www.stmsky.com/bbs/viewthread.php?tid=2738