static 关键字
static修饰局部变量
-
static用于修饰局部变量时,通常在某个函数体内,只能在此函数内调用。
void test() { int i = 0;// 若i的数据类型为int i++; printf("%d ", i); } int main() { int i = 0; for (i = 0; i < 10; i++) { test(); } return 0; }//因为 i 是局部变量,函数调用完之后,i的值被释放,当再次调用时,i为初值0 打印结果:1 1 1 1 1 1 1 1 1 1
void test() { static int i = 0;//若 i 的数据类型为static int i++; printf("%d ", i); }//static定义的变量,称为局部静态变量,存放在局部静态区,值不会因为随着函数调用的结束被释放,再次调用时,它的值是上一次调用结束后的值。 打印结果:1 2 3 4 5 6 7 8 9 10
修饰全局变量
-
static还可以修饰全局变量,该变量在某一个文件中,但不属于任何一个函数范围内,通常称为静态局部变量。
1.
test.c int a=2020;//在test文件中定义int类型的变量
创建了两个C文件,用extern声明外部符号
main.c extern a; int main() { print("%d",a); return 0; } 结果:2020
2.
test.c static int a=2020;//在test文件中定义int类型的变量
创建了两个C文件,用extern声明外部符号
main.c extern a; int main() { print("%d",a); return 0; } 结果:fatal error :1个无法无法解析的外部命令 // 报错
解释:一个全局变量本来是有外部链接属性的,但是被static修饰后,外部链接属性就变成了内部链接属性,只能在自己所在的源文件内部使用,不能在其他文件内部使用。
static修饰函数
-
static还可以用于修饰一个函数,这样的函数称之为静态函数
1.
test.c int add(int a,int b) { return a+b; }; //在test文件中定义返回值为int类型的函数
创建了两个C文件,用extern声明外部符号
main.c extern add(int a,int b); int main() { int a=2; int b=3; int ret =add(a,b); printf("%d",ret); return 0; } 结果: 5
2.
test.c static int add(int a,int b) { return a+b; }; //在test文件中定义返回值为static int类型的函数
创建了两个C文件,用extern声明外部符号
main.c extern add(int a,int b); int main() { int a=2; int b=3; int ret =add(a,b); printf("%d",ret); return 0; } 结果:结果:fatal error :1个无法无法解析的外部命令 // 报错
解释·:定义一个静态函数就是在函数的返回类型前加上static关键字。静态函数的作用域仅限于本文件,不能被其他文件调用。
const 关键字
修饰变量
-
变量前用const修饰,把变量声明为常量初始化后其值不能被修改
#include <stdio.h> //错误案例 int main() { const int a = 200; //const修饰成常量后a的值不能被修改 //const int a,int const a,两者写法不同,意义相同 a = 50; //错误,const修饰a为常量,常量a的值不能修改 printf("%d", a); return 0; }
修饰指针
-
指针常量:const修饰p,表示p所指向的内存地址不可以改变,但可以改变p指向的变量的值
//错误案例 int a = 1; int * const p = &a; p++;//错误,const修饰指针p,p指向的变量的内存地址不能改变 printf("%d\n", *p);
//正确案例 int a = 1; int * const p = &a; *p = 2;//正确,const修饰指针p,p指向的变量的值可以改变 printf("%d\n", *p);
-
常量指针:const修饰*p,表示p指针指向的变量的值不可以改变, 但可以改变p指向的内存地址
//错误案例 int a = 1; int const * p = &a; *p = 2;//错误,const修饰*p,*p的值不能被修改 printf("%d\n", *p);
//正确案例 int a = 1; int const * p = &a; printf("%p\n", p); p++;//正确,p的指向的地址可以改变 printf("%p\n", p); 结果: 0x7fffc8f3780c 0x7fffc8f37810 //指针偏移了4个字节,正好是一个int型变量占用的内存地址
-
const 修饰 ” * “ 与p,表示p指向的变量的值与p指向的地址都不能改变,” * “是解引用,用于获取指针p指向的变量的值,p是指针指向某段内存地
//错误案例 int a = 1; const int * const p = &a; *p = 2;//错误,p指向的变量的值不能改变 p++;//错误,p指向的地址也不能改变
修饰函数参数的指针形参
-
const char str作为函数参数:str被const修饰,它可以避免传递过来的值在函数体内部被错误修改
//错误案例 void printString(const char *str) { *str = "hello";//错误,const修饰*str,*str指向的变量的值不能被修改 printf("%s\n", str); } int main() { char s[] = "hello world!"; printString(s); printf("%s\n", s); return 0; }
修饰函数返回值
正确案例 #include <stdio.h> //const int getNum也可以写成int const getNum,两者意义相同 const int getNum(int x) { return x = 5; }//返回值类型是const int 即返回值不变,为5 int main() { int a = 2; int ret = getNum(a); printf("ret = %d\n", ret); return 0; } 结果: ret = 5 //getNum函数的返回值并没有被传递过来的实参a修改,因此,函数的返回值被const修饰后,可以确保函数的返回值在使用的过程中不会被修改
总之,const靠近谁,谁就不能被修改