*********************************************************续上篇*****************************************************************
3 关键字
C语言中关键字有很多,前面的几篇博客也有介绍。今天介绍后面需要用的一些关键字。
(1)Extern
extern可置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量或函数时,在其它模块中寻找其定义。
(2)static
在局部静态变量前面加上关键字static,该局部变量便成了静态局部变量。静态局部变量有以下特点:
1)该变量在全局数据区分配内存;
2)如果不显示初始化,那么将被隐式初始化为0;
3)它始终驻留在全局数据区,直到程序运行结束;
4)其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束。
在全局变量前面加上关键字static,该全局变量变成了全局静态变量。全局静态变量有以下特点:
1)在全局数据区内分配内存;
2)如果没有初始化,其默认值为0;
3)该变量在本文件内从定义开始到文件结束可见,即只能在本文件内使用。
在函数的返回类型加上static关键字,函数即被定义成静态函数。静态函数有以下特点:
1) 静态函数只能在本源文件中使用;
2) 在文件作用域中声明的inline函数默认为static;
说明:静态函数只是一个普通的全局函数,只不过受static限制,他只能在所在文件内使用,不能在其他文件内使用。
(3)const
我这里重点讲下const修饰指针:(举例说明)
const int *p; // p可变,p指向的对象不可变
int const *p; // p可变,p指向的对象不可变
int * constp; // p不可变,p指向的对象可变
const int *const p; // 指针p和p指向的对象都不可变
const也是就近原则,这点很重要。
(4)typedef
用法与 #define 有类似之处,typedef属于语句,赋予现有类型一个新的名字。
typedef在表现上有时候类似于 #define,但它和宏替换之间存在一个关键性的区别。正确思考这个问题的方法就是把 typedef 看成一种彻底的“封装”类型,声明之后不能再往里面增加别的东西。
1) 可以使用其他类型说明符对宏类型名进行扩展,但对 typedef 所定义的类型名却不能这样做。
2) 在连续定义几个变量的时候,typedef 能够保证定义的所有变量均为同一类型,而 #define 则无法保证。
4 位运算
位运算很好理解,我不做过多介绍了。
5 内存管理
计算机中的内存是分区来管理的,程序和程序之间的内存是独立的,不能互相访问,比如QQ和浏览器分别所占的内存区域是不能相互访问的。
(1) 程序结构分为栈区,堆区,数据区和代码区。
(2) 内存分配方式分为,静态分配和动态分配。其中静态分配有代码区和数据区,动态分配分为栈区系统分配和堆区程序员调用malloc系统函数分配。
内存管理中,我们还需要掌握相关函数,比如malloc、realloc、calloc、memset、free等,不一一介绍,具体用法可以上网查阅。
下面重点讲一下栈与堆的区别:
(1) 管理方式不同:栈编译器自动管理,无需程序员手工控制;而堆空间的申请释放工作由程序员控制,容易产生内存泄漏。
(2) 空间大小不同:栈是向低地址扩展的数据结构,是一块连续的内存区域;堆是向高地址扩展的数据结构,是不连续的内存区域。
(3) 是否产生碎片:对于堆来讲,频繁的malloc/free(new/delete)势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低(虽然程序在退出后操作系统会对内存进行回收管理)。对于栈来讲,则不会存在这个问题。
(4) 增长方向不同:堆的增长方向是向上的,即向着内存地址增加的方向;栈的增长方向是向下的,即向着内存地址减小的方向。
(5) 分配方式不同:堆都是程序中由malloc()函数动态申请分配并由free()函数释放的;栈的分配和释放是由编译器完成的,栈的动态分配由alloca()函数完成,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行申请和释放的,无需手工实现。
(6) 分配效率不同:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行。堆则是C函数库提供的,它的机制很复杂。