> 文档中心 > C语言高频考点const,快进来 > o < 一定有你不清楚的地方。

C语言高频考点const,快进来 > o < 一定有你不清楚的地方。


今天重点说一下const

(今天也要加油学习哦)在这里插入图片描述

1. const解释

const 是 constant 的缩写,是恒定不变的意思,也翻译为常量、常数等。很不幸,因为这一点,很多人都认为被 const 修饰的值是常量。这是不精确的,精确的说应该是只读的变量,其值在编译时不能被使用,因为编译器在编译时不知道其存储的内容。

2. const修饰一般变量

const修饰一般常量是指简单类型的只读变量。这种只读变量在定义时,修饰符 const 可以用在类型说明符前,也可以用在类型说明符后。一定要在定义const 修饰的变量时会进行初始化。因为没法再直接赋值。

例1

    const int a = 10;int const b = 20;

并且const修饰的变量不能直接修改。

例2

    const int a = 10;int const b = 20;a = 30;//err :左值指定 const 对象

有句话是这样说的:上帝给你关了门,就会给你开个窗,而在const这里,就是不能直接修改,那就间接修改,通过 指针 修改。
例3

    const int a = 10;int *p = &a;*p = 30;

在编译器上运行一下发现可以修改了,a值变为30了,但是会有个警告,叫做“初始化”: 不同的“const”限定符 这个是为什么呢?因为类型的原因,需要强制类型转化一下就不会报错了。
例4

    const int a = 10;int *p = (int*)&a;*p = 30;return 0;

但是可以下面的情况不用进行强转,也没有警告。

   const int a = 10;   int b = a;   const int* p = &b;   const int *q = p;

如果类型不同为什么没有报错呢?
tip 4:
这就是一个小经验,const int 比 int 类型更严格,那么编译器会默认把类型限定严格的赋给类型限定不太严格的不会报错,const int 和int*同理。*

3. const修饰数组

const修饰数组表示数组每个元素都是不可被修改,如果修改就会报错显示这个err :左值指定 const 对象

例5

    const int arr[5] = { 0 };arr[0] = 1;//err :左值指定 const 对象arr[1] = 2; arr[2] = 3; arr[3] = 4; arr[4] = 5;
     tip 3:何为左值?,何为右值?  int  x = 10;     左值:等号左边的值,一般指变量的空间,变量的属性。     右值:等号右边的值,一般指变量的内容,数据的属性。

有没有想过用const修饰的变量来定义数组呢?语法支持吗?
例6

    const int a = 10;int arr[a] = { 0 };//err :应输入常量表达式

在vs2013中是不支持的,但是在gcc下可以通过的,为什么呢?
因为gcc也支持自己的(GUN)标准。但是为了代码可以移植性,在标c下不使用。

4. const修饰指针

说起指针,有些读者就会困惑,后续会专门发一篇博客来阐述指针和指针变量区别,以及指针相关内容。现在就浅谈下const中的指针,const修饰指针,分为下列几种情况:
例7

    int a = 10;int *p = &a;const int *p = &a; // p 可变,p 指向的对象不可变int const *p = &a; // p 可变,p 指向的对象不可变int *const p = &a; // p 不可变,p 指向的对象可变const int *const p = &a; //指针 p 和 p 指向的对象都不可变return 0;

先忽略类型名(编译器解析的时候也是忽略类型名),我们看 const 离哪个近。“近水楼台先得月”,离谁近就修饰谁”
这个时候就在来考虑左右值得问题。
const修饰的左值不可被修改,那么就看谁是左值啦。
类型名去掉在分析。
看const修饰 *p 还是 p 了,*p表示a,即a的值不可改变。修饰 p表示 p不可变,即不能给 p赋值其他地址。这里还有一个问题 p 是真的不能修改吗?
p的值是可以通过二级指针间接修改的。有兴趣可以运行下。
例8

    int a = 10;int b = 0;int * const p = &a;*p = 20;//改变a值printf("%d\n", *p);//  20int **pc = (int **)&p;//取出p的地址*pc = &b;//对p地址修改printf("%d\n", *p);//  0

5. 修饰函数形参

const 修饰函数形参,实际上就是不想改变这个函数形参的值。
例9
这里的a不希望被改变,所以加const修饰

int Test(const int a){if (a == 10){return 1;}else{return 0;}}int main(){int a = 10;int ret = Test(a);printf("%d\n", ret);return 0;}

6. 修饰函数返回值

const修饰函数返回值也是不想通过其他人为的进行对函数返回值进行改变
例10:
这里的ret要用const int*来接收,否则会报警告。

const int* Test(){static a = 10;return &a;}int main(){    const int *ret = Test();//int *ret = Test();//“初始化”: 不同的“const”限定符printf("%d\n", ret);return 0;}

7. const与define宏的区别

剩下还有就是const与define宏的区别,但实际对我们学习帮助有限不再说了
提供点资料阅读:

const 定义的只读变量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const 定义的只读变量在程序运行过程中只有一份拷贝(因为它是全局的只读变量,存放在静态区),#define 定义的宏常量在内存中有若干个拷贝。#define 宏是在预编译阶段进行替换,而 const 修饰的只读变量是在编译的时候确定其值。#define 宏没有类型,而 const 修饰的只读变量具有特定的类型

2.1 static修饰局部变量
2.2 static修饰全局变量
2.3 static修饰函数
2.4 static和const区别


下期更新,下期更精彩

本来是要写完呢,但是一看篇幅太长,就怕各位看官没有耐心看完,就截断了,今天如果晚上更新static相关知识。请稍后。

加粗字体和tip是真的很有用 !!!