目录
const关键字
概念
const是C语言的关键字,可以将变量设置为只读,在程序运行过程中不被修改。其实const称为只读关键字可能更恰当一些,也更容易理解和记忆。
1. 修饰基本类型变量
const可以用来修饰整形、字符型、浮点型等变量。
举例说明:
const int data;
将data声明为一个整数,data是只读的,不能修改。
给其赋值的方法是在定义式声明中直接初始化。
const int data = 1099;
const char simple = ‘ A ’;
const char words[50] = “ Hello World !”;
const double digital = 3.56;
2. 修饰派生类型变量
2.1 修饰指针
2.1.1 指向常量的指针(也叫 常量指针 或 指向const的指针)
定义如下:
const int* data_p; data_p是一个指向整形常量的指针。
常量指针本质上讲是一个指针,常量修饰它,表示这个指针乃是一个指向常量的指针。
该常量是该指针指向的属性,而不是指具体指向的某个量(变量)是常量!
指针指向的对象本身可以是一个变量,这个对象可以被修改,但是不能通过该指针(常量指针)来修改。
同时,也可以修改指针本身的值,指针本身也不是常量(只读)!
举例:
const int* data_p;
int const *data_p;
第一种与第二种写法等价,但是不建议用第二种写法,建议使用第一种写法。
不管是第一种还是第二种,const修饰的是指针所指向的变量。
int data = 12;
const int* data_p = &data;
进一步解释:
把data_p指向的int类型的值声明为const,注意,这种操作并不指定data_p必须指向哪个具体的变量(也可以理解为并不规定必须指向哪个内存地址),只是规定了一旦指向了某个变量(内存地址),那么就不能使用该指针改变该内存地址中的值,但是可以使用变量本身的名称来改变该内存地址中的值。当然,也可以改变该指针本身的值,即可以让他指向其他的内存地址或变量。
常量指针在函数传参的时候非常有用!
举例:
int data =32;
const int* data_p; data_p是一个指向整形常量的指针。
data = 100; 是允许的
*data_p = 100; 是不允许的!
int data_array[20] = {5,3,20,0};
const int* da_p = data_array;
int other;
*da_p = 100; 不允许,
*(da_p + 2) = 100; 不允许,
da_p[2] = 100; 不允许,与上一个表示等价,无论使用指针表示法还是数组表示法,都不允许使用 da_p修改它所指向的数据的值
other = *(da_p++); 允许,允许da_p指向其他地方,此时da_p内的值已经改变
data_array [2] = 100; 允许
抛出问题:指针可以直接使用下标引用吗?可以,见博客指针表示法与数组表示法。
注意:无论是用指针形式访问,还是用数组下表的形式访问,都不允许使用da_p修改其所指向的数据的值!
但是可以通过data_array修改数组元素的值,因为data_array不是const类型。
2.1.2 指针自身是常量(也叫 指针常量 或 const指针)
定义如下:
int* const data_p; data_cp本身是常量
data_cp 是一个指向整形的常量指针。此时,指针是常量,指针里存储的内存地址是不允许修改的,但是可以通过该指针修改它所指向的类型的值。
可以使用这种指针修改它所指向的值,但是指针本身只能指向它初始化时设置的地址!
举例:
int* const data_p;
const修饰的是指针本身。
进一步解释:
举例:
int data_array[20] = {5,3,20,0};
int* const da_p = data_array;
int other;
*da_p = 100; 允许
*(da_p + 2) = 100; 允许
other = *(da_p++); 不允许,不允许da_p指向其他地方,此时da_p内的值已经改变
da_p[2] = 100; 允许
data_array[2] = 100; 允许
常量指针与指针常量总结:
常量指针,指针指向的值不能变。(不能使用指针改变所指向的地址内的值)。
指针常,指针自身的值不能变(指针里面存放的内存地址不能修改,但是可以改变他指向的变量的值)
2.1.3 指向常量的常量指针
定义如下:
const int* const data_p;
创建指针时使用两次const,该指针既不能更改它所指向的地址,也不能通过指针修改其所指向的地址上的值。
举例:
int data_array[20] = {5,3,20,0};
const int* const da_p = data_array;
int other;
*da_p = 100; 不允许
da_p = &other; 不允许
da_p = &data_array[19]; 不允许
2.2 修饰数组
以const关键字修饰(声明)的对象,它的值不能够通过赋值,递增或递减来修改。
所以,对于数组,结构体,枚举和联合。const的作用是对这些数据结构中存放的数据在程序运行的过程中进行只读限定。
举例:
const int months[12] ={ 1,23,4,5,6,7,8,9,10,11,12};
2.3 修饰结构体
struct month
{
int month_num;
char* month_name[12];
}
const struct month_ch =
{
12,
{"January","February","March","April","May","June",
"July","August","September","October","November","December"},
};
2.4 修饰枚举
const enum months =
{January,February,March,April,May,June,
July,August,September,October,November,December};
2.5 修饰联合
const union student_message =
{
char name[20];
int age;
float score;
} student_message = {“Xiao ming”};
初始化联合体时,只能对第一个成员赋初值 将联合体声明为const并没有什么实际用处。
3. 使用要点
关于指针赋值和const一起使用时需要注意,把const数据或非const数据的地址初始化为指向常量的指针 或为其赋值是合法的!
但是,只能把非const数据赋值给普通指针,否则通过普通指针就能改变const数组中的数据。
举例:
int data_array[20] = {5,3,20,0};
const int months[12] = { 1,23,4,5,6,7,8,9,10,11,12};
const int * pc = data_array; 有效
pc = months; 有效
pc = &data_array[2]; 有效
注意:只能把非const数据的地址赋值给普通指针!
不能将const数据的地址赋值给普通指针,否则通过指针就能改变const类型变量中的数据!
举例:
int data_array[20] = {5,3,20,0};
const int months[12] = { 1,23,4,5,6,7,8,9,10,11,12};
int * pc = data_array; 有效
pc = months; 无效,不能将const数据的地址赋值给普通指针
pc = &data_array[2]; 有效
4.问题解答
4.1可以将const数据的地址赋值给常量指针吗?
可以,见《3.指针初始化注意》中的讲解
4.2可以将const数据的地址赋值给指向常量的指针吗?
可以,指向常量的指针就是常量指针,不同的叫法而已。
4.3指针常量怎初始化?
指针常量存储的地址值是不能改变的。不同变量的内存地址是不同的,只能在初始化的时候,让指针常量指向某个变量,初始化后不能再指向其他的地址。
4.4 data_p是一个指向常量的指针,指向整形常量数组首元素,那么可以通过pd修改数组第三个元素的值吗?
答案:不可以,不能使用该指针改变其指向的内存地址中的值,即使它要指向的地址不是该指针指向的地址,是其后的某个地址中的值,使用该指针计算或偏移实现的也是不可以的。
4.5常量指针怎么初始化?
常量指针可以在声明的时候初始化,也可以在程序运行过程中对其进行赋值。