static
修饰变量
这个static其实一点都不安静,这不,你得注意以下几点:
静态全局变量
作用域只限于从定义处开始,到文件结尾处,即使你使用extern去申请也不管用的。
静态局部变量
在函数体里定义,就只能在这个函数体里面使用,同一文件的其他的函数使用也是 不行的,由于被static修饰??的存放在内存的静态区,就是这个函数运行结束, 变量也不会被撤销。
#include<stdio.h>
static int j;
void fun1(void)
{
static int i = 0;
i ++;
printf("\n");
printf("static's i= %d\t",i);
}
void fun2(void){
j = 0;
j ++;
printf("\n");
printf("non-static j=%d\t",j);
}
int main(){
int k;
for(k = 0; k < 10; k++){
fun1();
fun2();
}
return 0;
}
下面是该段程序的运行结果:
static's i= 1 non-static j=1 static's i= 2
non-static j=1 static's i= 3 non-static j=1
static's i= 4 non-static j=1 static's i= 5
non-static j=1 static's i= 6 non-static j=1
static's i= 7 non-static j=1 static's i= 8
non-static j=1 static's i= 9 non-static j=1
static's i= 10 non-static j=1
从这里我们可以看出来,fun1()内的静态变量没有被释放,还是维持着 上次运行的结果。
修饰函数
这里的修饰,是应该它本来的面目,也就是指该函数只对该文件有效,这样, 不同的人在一个大型项目中不必担心命名冲突。linux kernel中充斥着大量的 static.
void
作用两个: 1) 对函数返回的限定 2) 对函数参数的限定
指针
如果p1和p2的指针类型相同,我们可以在p1和p2之间相互赋值,如果P1和P2 指向不同的数据类型,则必须使用强制类型转换运算符把赋值运算符右边的 指针类型转换为左边指针的类型。 例如:
float *p1;
int *p2;
p1 = p2;
最后一句是错误的,必须按照
p1 =(float *)p2;
来赋值。 但是不能将void类型的指针赋值给有类型的指针。
补充
该标准规定不能对void类型的指针进行算法运算,因为不知道该指针的类型(存储空间)。 但是,GNU委员会不这么认为,它规定void * 的类型与char * 的类型一致。所以, 你想写出移植行很高的代码,需要进行如下的操作:
void *pvoid;
(char *)pvoid++;//ANSI: right
(char *)pvoid += 1; //ANSI: errors
修饰返回值和参数
默认不显式的声明函数的类型,则默认为int
如果函数参数为空,最好声明为void
如果函数的参数可以是任意的指针,应该声明为void *.
例如,内存操作函数:
void *memcpy(void *dest, const void *src, size_t len);
void *memset(void *buffer, int c, size_t num);
这样,任何类型的指针都可以传入memset和memcpy中,
const
const 修饰的只读变量只能在定义的同时初始化:
const int Max = 10;
修饰一般变量
int const i = 2; 或者 const int i = 2;
修饰数组
int const a[5] = {1,2,3,4,5};
const int a[5] = {1,2,3,4,5};
修饰指针
const int *p;// const 修饰*p,p是指针,*p是指针指向的对象,不可变
int const *p;
int *const p;
const int *const p;
以上情况有些复杂,我们需要仔细的分析。
编译器解析的时候首先忽略类型名,这里,我们也需要先忽略类型名。 我们看const离谁近,就修饰谁。
const int *p;
int const *p;
int *const p;
const int *const p;
修饰函数的参数
const 修饰符也可以修饰函数的参数,当不希望这个参数被函数体内意外改变使用。 例如:
void Fun(const int i);
修饰函数的返回值
const 修饰函数时,返回值不可改变.
const int fun(void)
在另一连接文件中引用const只读变量:
extern const int i;
volatile
这个关键词大概见过几次,我只是简单的了解到,使用了这个修饰符,编译器不再对 代码进行优化。请看例子:
int i = 10
int k = i;
int j = i;
这里,由于i除了第一句被用作了左值,后两条被用作了右值,也就是说在编译器将i 的值赋值给j后,编译器并没有将i的值立即丢掉,马上将i的值赋值给了k,也就是这 一步,不用经过内存访问,这里提高了效率。
再看下面的例子:
volatile int i = 10;
int k = i;
int j = i;
这里,volatile 关键字告诉编译器,i是随时可以改变的,每次使用它时变量必须每次 从内存中取出来,也就是不能把i的是使用两次