老规矩,先上几个问题。
一、const 关键字修饰有什么效果,当它修饰指针时,你能区分const int* a、int * const a、int const *a、const int * const a的区别吗?
二、用#define a 20 和const int a=20;声明常量时,有区别吗?如果有一般建议那种写法?
三、C链接属性你了解吗,链接属性(external 外部的、internal 内部的 none 无),关键字extern的使用。
四、static关键字你了解吗?知道它修饰函数定义、代码块之外变量声明和代码块内部变量声明的不同效果吗?效果有是什么?
一、const的使用
(1) 首先const关键字可以用来声明常量,这有什么用呢?
显然当我们需要常量时,比如Π我们要声明为3.14,这个值我们不希望程序修改,我们声明为常量,这样程序就不会被运行时意外修改。
(2)const 修饰指针时怎么区分,有什么作用?
const int *a 时,它所指向的值(*a)不可以修改,但是指针可以修改。也就是常量指针,下面这种写法是可以的,但是你去给*a=20赋值,编译器马上就会报错。
int c=10;
int b=1;
const int *a=&c;
a=&b;
int const *a时,它所指向的值(*a)不可以修改,但是指针可以修改。也是常量指针,同理下面代码是合法的。
int c=10;
int b=1;
int const *a=&c;
a=&b;
int* const a时,它指向的指针不可以修改,但是它指向的值(*a)可以修改。也就是指针常量
int c=10;
int* const a=&c;
*a=20;
const int* const a时,它指向的指针和值都不可以修改。可以从下图看出两种修改都报错了。
![](https://i-blog.csdnimg.cn/blog_migrate/a3cd99780a0f312067db452cde0daae3.png)
记忆技巧,因为const 和int的位置可以互换,所以第一种情况可以看作第二种变式,因为const 后面都接的是*a,所以可以看出*a是不可以修改的,但是指针可以修改;第三种const 修饰a,所以指针不可以修改,但指向的值可以修改。最后一种const既修饰了*a又修饰了a,所以都不可以修改。
二、两者的不同
首先两者是有区别的,#define 声明的常量是可以在任何允许使用常量的地方使用,比如数组的长度,但是const修饰的就不同了,它只允许在使用变量的地方使用,从这个情况,选择#define声明更好。
![](https://i-blog.csdnimg.cn/blog_migrate/181a498d15ab76c078b4673174f88ec4.png)
三、链接属性的讲解
(1)external 链接属性的变量和函数,位于几个源文件都表示同一个实体,什么意思呢?也就是说像extern关键字修饰的变量或函数,在不同的源文件test.c和testpro.c中,指向是同一个实体。有什么作用,请看下面例子。
1.1extern 修饰函数时
test.c代码写一个加法函数
extern int add(int a, int b)
{
return a + b;
}
testpro.c中直接声明两个变量,和函数声明就可以直接调用test.c中的加法函数
#include<stdio.h>
int main()
{
int a=20, b=30;
int add(int a, int b);
printf("the result is %d", add(a, b));
return 0;
}
运行结果图
![](https://i-blog.csdnimg.cn/blog_migrate/3f35897db52585661d1c17f5d93573f2.png)
但是是不是一定要写extern关键字呢?对于全局变量和文件作用域的函数(也就是嵌套的函数,main代码块内函数),他们可以不写extern 关键字,因为他们在缺省的状态,就是外部的链接属性。
1.2extern 修饰变量
test.c 代码声明也extern变量,根据上面知识,extern 也可以省略,直接int a=20也可以。
extern int a=20;
testpro.c中在代码块作用域中要用extern声明a,但声明全局变量就可以不要,因为全局变量缺省状态也是external属性
#include<stdio.h>
int main()
{
extern int a;
printf("the value is %d", a);
}
代码运行效果(可以看到它将test.c源文件中a的值直接在test.pro中打印出来,说明他们是一个实体)
![](https://i-blog.csdnimg.cn/blog_migrate/de81b82641a4c78689cf942792dbe581.png)
(2)internal(内部的)链接属性的标识符在同一个源文件的所以声明都指向一个实体,不同的源文件指向不同的实体。但是可以通过加extern关键字改变链接属性为外部属性。同理static也可以使缺省为external属性的标识符变为internal属性。就不举例子了。
(3)none链接属性的标识符总是被当作单独的个体。在代码块作用域(花括号{}内的代码是代码作用域)中的声明标识符为none链接属性。
四、static关键字
(1)static 修饰函数定义时,或用于代码块之外的声明时,static改变标识符的链接属性(从external 外部的到internal 内部的)但标识符的存储类别和作用域不受影响。用这个声明的函数或变量只可以在声明他们的源文件中使用。
(2)static修饰代码块内部变量声明时,static用于修饰变量的存储类别,从自动变量变为了静态变量,但变量的链接属性和作用域不会改变,用这种声明的变量在程序执行之前创建,并在程序整个运行阶段都存在,在代码执行完毕后销毁,也就说变量的生命周期变长了,但作用域没有变,依然不可以在代码块之外使用这个变量。