目录
const讲解
1、const 放在*的左边
2、const 放在*的右边
static讲解
1、static修饰局部变量
2、extern关键字
3、static修饰全局变量
4、static修饰函数
const讲解
const int n = 10;
n = 0;
如上述代码,代码运行后会报错,会提示:左值指定 const 对象。
因此,如果我们使用了 const 去修饰一个变量,那么这个变量就无法被改变。
此处的const是常属性,代表着由其修饰的变量不能被修改了;可即使 n 不能被修改了,他依然还是个变量,他被叫做常变量。在C89中,数组长度是不允许使用变量的,当我们将一个由const修饰的变量来表示数组长度,依旧会报错:应输入常量表达式。由此可见,const修饰的变量依旧是变量。
思考:(以上述代码为例)如果我们开创一个指向 n 变量地址的指针,那么通过指针来改变 n 的值,是否可以呢?
int* p = &n;
*p = 20;
答:可以。const所修饰的只是n这个变量,而不是指向n地址的指针;解引用p指针,修改其值,最后p指向的n变量地址里存放的值改变了,也就完成了改变n的值的效果。
如果使用const去修饰指针变量,共会分成以下两种情况: const int* 、int* const
1、const 放在*的左边
const int n = 10;
int m = 100;
const int* p = &n;
*p = 20; //代码1
p = &m; //代码2
上述代码中,代码1会报错,代码2能够正常运行。
const 放在*的左边,限制的是*p,意思是不能通过p来改变p指向的对象的内容,但是p指针本身是可以被改变,它可以指向其他对象的地址
代码1:解引用操作被限制了,不能对p指针进行解引用操作
代码2:p指针所指向的地址被改变了,并没有对p指针进行解引用操作
2、const 放在*的右边
const int n = 10;
int m = 100;
int* const p = &n;
*p = 20; //代码1
p = &m; //代码2
上述代码中,代码1能够正常运行,代码2会报错。
const 放在*的右边,限制的是p,意思是不能改变p本身的值,但是p指向的内容是可以通过p来改变的。
代码1:对p进行解引用操作,并重新赋值
代码2:将p指针指向新的空间地址
总结:左边不可解引用,右边可以解引用。
static讲解
1、static修饰局部变量
void test()
{
static int a = 1;
a++;
printf("%d", a);
}
int main()
{
int i = 0;
while (i < 10)
{
test();
i++;
}
return 0;
}
以上代码的结果不为10个2,而是2 3 4 5 6 7 8 9 10 11
原因解析(代码讲解):
static 修饰的变量出了作用域是不会销毁的。本质上,static修饰局部变量的时候,变量会在静态区分配内存;这影响了变量的生命周期,生命周期变长,和程序的生命周期一样
程序经历的六个阶段(生命周期):
1.编译 2.预处理 3.编译 4.汇编 5.链接 6.执行
请注意,上述代码中,由static修饰的变量a的值只是不会在每次调用函数时重新创建赋值,但这不是说它就是个全局变量;a是变成了静态局部变量,使得每次调用test的时候a不会被重置。这就有点像局部变量没了创建和销毁的过程。
在进行static修饰全局变量或函数的讲解以前,我们先得了解一个名为“extern”的关键字
2、extern关键字
extern被称为“声明外部符号”,如果有两个文件(如下图),我们想要在test.c文件调用add.c文件中的内容,那么就必须通过extern关键字告知编译器
3、static修饰全局变量
当使用了static修饰g_val这个变量以后,test.c文件中就不能使用g_val这个变量了
原因讲解:static修饰全局变量的时候,这个全局变量的外部链接属性就变成了内部链接属性。其他源文件(指的是 .c 问卷)就不能再使用到这个全局变量了。
4、static修饰函数
一个函数本身是具有外部链接属性的,因此如果在test文件中不使用“extern”关键字,程序只会报一个警告,但并不会因为没有这个关键字而报错运行不起来。函数外部声明方式如上图。(最好还是声明以下,以防程序出问题)
但函数被static修饰的时候,外部链接属性就变成了内部链接属性,其他源文件就不能使用了。