【C基础知识】const知识大全

【0】概述

const是constant 的缩写,是C语言的关键字之一,是一个类型修饰符(type specifier)。const是恒定不变的意思也翻译为常量、常数等。很不幸,正是因为这一点,很多人都认为被 const 修饰的值是常量。这是不精确的,精确的说应该是只读的变量,其值在编译时不能被使用,因为编译器在编译时不知道其存储的内容。或许当初这个关键字应该被替换为 readonly。那么这个关键字有什么用处和意义呢?

它限定变量为只读变量,即变量保存在只读静态存储区。编译时,如何尝试修改只读变量,则编译器提示出错,就能防止误修改。使用const在一定程度上可以提高程序的安全性和可靠性。const 推出的初始目的,正是为了取代预编译指令,消除它的缺点,同时继承它的优点。

【1】作用

1.1 const 修饰的只读变量

例如:

1 const int Max=100;
2 int Array[Max];

这里请在 Visual C++6.0 里分别创建.c 文件测试一下。你会发现在.c 文件中,编译器会提示出错,这也从侧面证实在 C 语言中,const 修饰的 Max 仍然是变量,只不过是只读属性罢了

1.2节省空间,避免不必要的内存分配,同时提高效率

编译器通常不为普通 const 只读变量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的值,没有了存储与读内存的操作,使得它的效率也很高。

例如:

1 #define M 3 //宏常量
2 const int N=5;     //此时并未将 N 放入内存中
3 ......
4 int i=N; //此时为 N 分配内存,以后不再分配!
5 int I=M; //预编译期间进行宏替换,分配内存
6 int j=N; //没有内存分配
7 int J=M; //再进行宏替换,又一次分配内存!

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

1.3修饰一般变量

一般常量是指简单类型的只读变量。这种只读变量在定义时,修饰符 const 可以用在类型说明符前,也可以用在类型说明符后。例如:

1 int   const   i=2;
2 //或
3 const   int   i=2;

1.4,修饰数组

定义或说明一个只读数组可采用如下格式:

1 int const a[5]={1, 2, 3, 4, 5};
2 //或
3 const int a[5]={1, 2, 3, 4, 5};

1.5,修饰指针

1 const int *p;          // p 可变,p 指向的对象不可变
2 int const *p;         // p 可变,p 指向的对象不可变
3 int *const p;         // p 不可变,p 指向的对象可变
4 const int *const p; //指针 p 和 p 指向的对象都不可变

给出一个记忆和理解的方法:

先忽略类型名(编译器解析的时候也是忽略类型名),我们看 const 离哪个近。“近水楼台先得月”,离谁近就修饰谁。

1 const int *p;          //const 修饰*p,p 是指针,*p 是指针指向的对象,不可变
2 int const *p;         //const 修饰*p,p 是指针,*p 是指针指向的对象,不可变
3 int *const p;         //const 修饰 p,p 不可变,p 指向的对象可变
4 const int *const  p; //前一个 const 修饰*p,后一个 const 修饰 p,指针 p 和 p  指向的对象都不可变

const int *a
这里const 修饰的是int,而int定义的是一个整值
因此*a 所指向的对象 值 不能通过 *a 来修改,但是 可以重新给 a 来赋值,使其指向不同的对象
eg:

1  const int *a = 0;
2  const int b = 1;
3  int c = 1;
4  a = &b //ok! 额外:注意不能通过a 来修改 b值
5  a = &c //ok! 额外:虽然c本身不是一个常量
6  *a = 2 //erro! 为题就在这里,不能修改通过 *a 所指向的对象值,最后赋值得对象是c,因此不能通过*a 来修改c值。

int const *a

和 const int *a 的意义是相同的 他们两个的作用等价

int *const a  
这里const修饰的是 a ,a代表的是一个指针地址因此不能赋给a其他的地址值,但可以修改a指向的值这有点和cont int *a相反的意味

const int * const a 
这个代表a所指向的对象的值以及它的地址本身都不能被改变

1.6,修饰函数的参数

const 修饰符也可以修饰函数的参数,当不希望这个参数值被函数体内意外改变时使

用。例如:

void Fun(const int i);

告诉编译器 i 在函数体中的不能改变,从而防止了使用者的一些无意的或错误的修改。

1.7,修饰函数的返回值

const 修饰符也可以修饰函数的返回值,返回值不可被改变。例如:

const int Fun (void);

在另一连接文件中引用 const 只读变量:

extern const int i;         //正确的声明
extern const int j=10; //错误!只读变量的值不能改变。

【3】Q&A

Q:

constdefine的区别?

A:

两者都可以用来定义常量,但是const定义时,定义了常量的类型,所以更精确一些(其实const定义的是只读变量,而不是常量)。#define只是简单的文本替换,除了可以定义常量外,还可以用来定义一些简单的函数,有点类似内置函数。const和define定义的常量可以放在头文件里面。(小注:可以多次声明,但只能定义一次)

关于const的点滴补充:
1、const 对象的地址只能赋值给指向const 对象的指针
2、指向const 对象的指针可以 被赋 以 一个非const 对象的地址 
3、指向const 的指针常被用作函数的形式参数,保证被传递给函数的实际对象在函数得实际对象在函数中不会被修改
4、常量在定义后就不能被修改,所以它必须被初始化。未初始化的常量定义将导致编译错误(上面都是在说明const得问题,所以没有赋值,实际语句中要赋值的)

时间: 2024-10-13 22:13:31

【C基础知识】const知识大全的相关文章

python基础知识部分练习大全

python基础知识部分练习大全   1.执行 Python 脚本的两种方式 答:1.>>python ../pyhton.py 2. >>python.py   #必须在首行有 #!/usr/bin/env python3 指定执行语言 2.简述位.字节的关系 答:一个字节(byte)=8位(bit)  位为最小的单位 3.简述 ascii.unicode.utf-8.gbk 的关系 ascii:只能表示256个符号 unicode:万国码,各国都有 需要有2位来表示 utf-8

iOS基础——通过案例学知识之LaunchScreen、APPIcon、StatusBar、UIScrollView、UIPageControl

iOS基础--通过案例学知识之LaunchScreen.APPIcon.StatusBar.UIScrollView.UIPageControl 今天要实现的案例效果图 一.LaunchScreen 1.设置程序的LaunchScreen 在项目配置文件中配置启动页,并且在LaunchScreen.storyboard中进行布局 2.设置LaunchScreen时间 //单位:秒 [NSThread sleepForTimeInterval:1.5f]; 二.APPIcon 1.命名规则:iOS

SVG的基础概念等知识,以及SVG与CANVAS的区别

本文主要介绍了SVG的基础概念等知识,以及SVG与CANVAS的区别,最后给出了一个简单示例,方便大家更好的了解SVG可缩放矢量图形.推荐给大家. SVG可缩放矢量图形(Scalable Vector Graphics)是基于可扩展标记语言(XML),用于描述二维矢量图形的一种图形格式.SVG是W3C制定的一种新的二维矢量图形格式,也是规范中的网络矢量图形标准.SVG严格遵从XML语法,并用文本格式的描述性语言来描述图像内容,因此是一种和图像分辨率无关的矢量图形格式. 什么是SVG? SVG 指

iOS基础——通过案例学知识之UITableView(上)

iOS基础--通过案例学知识之UITableView(上) 对于UITableView的知识点特别多,因为它是iOS用得最多控件之一,我会尽我最大努力和语言的组织,将所有知识点介绍到位,今天要实现的效果图 吐槽 与Android对比,可以说跟ListView的实现几乎一样,跟RecyclerView一模一样 Android写起来似乎比iOS复杂一点,因为iOS大部分都被封装好了,这一点iOS做得好 对于iOS的方法的命名只能说又长又臭 知识点包括 UITableView的UITableViewD

知识图谱基础知识之三——知识图谱的构建过程

前两次介绍了知识图谱的基本概念和知识图谱的构建方式,这次介绍一个知识图谱系统的构建过程. 1 知识图谱的总体构建思路 如图所示,从原始的数据到形成知识图谱,经历了知识抽取.知识融合(实体对齐).数据模型构建.质量评估等步骤. 原始的数据,按照数据的结构化程度来分,可以分为结构化数据.半结构化数据和非结构化数据,根据数据的不同的结构化形式,采用不同的方法,将数据转换为三元组的形式,然后对三元组的数据进行知识融合,主要是实体对齐,以及和数据模型进行结合,经过融合之后,会形成标准的数据表示,为了发现新

[nRF51822] 11、基础实验代码解析大全 · 实验16 - 内部FLASH读写

 一.实验内容: 通过串口发送单个字符到NRF51822,NRF51822 接收到字符后将其写入到FLASH 的最后一页,之后将其读出并通过串口打印出数据. 二.nRF51822芯片内部flash知识: EN-nRF51D 开发板使用NRF51822 芯片为nRF51822-QFAA,如下图所示,共有256KBFLASH,256 页,页大小为1024 字节. NRF51822 内部FLASH 写流程如下: 三.代码解析: main: 1 int main(void) 2 { 3 ... 4 5

[nRF51822] 10、基础实验代码解析大全 · 实验15 - RTC

一.实验内容: 配置NRF51822 的RTC0 的TICK 频率为8Hz,COMPARE0 匹配事件触发周期为3 秒,并使能了TICK 和COMPARE0 中断. TICK 中断中驱动指示灯D1 翻转状态, 即指示灯D1 以8Hz 的速率翻转状态 COMPARE0 中断中点亮指示灯D2 二.nRF51822的内部RTC结构: NRF51822 有两个RTC 时钟:RTC0,RTC1.两个RTC 均为24 位,使用LFCLK 低频时钟,并带有12 位分频器,可产生TICK.compare 和溢出

[nRF51822] 12、基础实验代码解析大全 · 实验19 - PWM

一.PWM概述: PWM(Pulse Width Modulation):脉冲宽度调制技术,通过对一系列脉冲的宽度进行调制,来等效地获得所需要波形. PWM 的几个基本概念: 1) 占空比:占空比是指在一个周期内,信号处于高电平的时间占整个信号周期的百分比,方波的占空比是50%. 2) 调制频率:周期的倒数. 3) 脉冲宽度:信号处于高电平的时间. 二.nRF51822的PWM产生: NRF51822 通过Timer.PPI 和GPIOTE 的配合实现PWM 的功能,由Timer 产生一个事件,

linux基础学习笔记——操作大全

作者:liaoyi 更新时间:2014-6-2 ****************基本操作***************** 关机 shutdown -h now    root用户               init 0              root用户halt      root+一般用户poweroff 重启shutdown -r now    root用户init6     root用户reboot            root+一般用户 注意:1.shutdown 比较灵活,可

【c++基础】const、const指针、const引用

一.const常量 声明时必须同时初始化(和“引用”一样) 二.const指针 三.const引用 引用本身和引用的对象都是const对象,可以用字面值来赋给const引用(普通引用则不行) 1 const B=1024; 2 const refB=B; //const变量的声明和初始化 3 4 const int &r=42;//字面值给const赋值 5 int &r2=42;//错 [c++基础]const.const指针.const引用