const 只读变量
·const 修饰的变量是只读的,本质还是变量
·const 修饰的局部变量在栈上分配空间
·const 修饰的全局变量在全局数据区分配空间
·const 只在编译期有用,在运行期无用
const 修饰的变量不是真的变量,它只是告诉编译器该变量不能出现在赋值符号的左边
const 全局变量的分歧
注意:
标准 C 语言编译器不会将 const 修饰的全局变量存储于只读存储区中,而是存储于可修改的全局数据区,其值依然可以改变。如果存储在只读存储区就会报错。
const 的变量本质例子 9 -1:
include “stdio.h”
const int g_cc = 2;
int main()
{
const int cc = 1;
int *p = (int)&cc;
printf("%d\n",cc);
*p = 3;
printf("%d\n", cc);
printf("g_cc = %d\n", g_cc);
p = (int*)&g_cc;
*p = 4;
printf("g_cc = %d\n", g_cc);
return 0;
}
输出结果:
1
3
g_cc = 2
输出结果根据编译器进行输出,不同的编译器对 const 变量赋值地址的输出是不一样的。
const 的本质:
·C 语言中的 const 使得变量具有只读属性
·现代 C 语言编译器中的 const 将具有全局生命周期的变量存储于只读存储区
const 不能定义真正意义上的常量。
例子 9 -2:
include”stdio.h”
const int g_array[5] = {0};
void modify(int*p,int v)
{
*p = v;
}
int main()
{
const int i = 0; //const 与 int 没有先后顺序
const static int j = 0; // 因为 j 为全局变量,但是经过 static 修饰之后,变为具有全局变量性质,用 const 修饰全局变量是不允许修改的
int const array[5] = {0};
modify((int *)&i, 1); //ok
//modify((int *)&j, 2); //error
modify((int *)&array[0], 3); //ok
//modify((int *)&g_array[0], 4);//error 编译只读存储区
printf("i = %d\n",i);
printf("j = %d\n", j);
printf("array[0] = %d\n", array[0]);
printf("g_array[0] = %d\n", g_array[0]);
}
输出结果:
i = 1
j = 0
array[0] = 3
g_array[0] = 0
const 修饰函数参数和返回值
·const 修饰的函数参数表示在函数体内不希望改变参数的值
·const 修饰函数返回值表示返回值不可无改变,多用于返回指针的情形
const 修饰函数参数与返回值 9 -3.c
include “stdio.h”
const char *f(const int i)
{
// i = 5; // 因为 i 被 const 修饰,所以 i 为常量,不能做左值
return "zhangyingli";
}
int main()
{
const char *pc = f(0); // 因为函数 f 为 const char 类型的,所以定义指针也得是 const char 型
printf("%s\n",pc);
pc[6] = '_'; //error *pc 为 const 类型的不能重新赋值
printf("%s\n",pc);
return 0;
}
输出结果:
报错
·volatile 可理解为“编译器警告指示字”
·volatile 告诉编译器你必须每次去内存中去变量值
·volatile 主要修饰可能被多个线程访问的变量
·volatile 也可以修饰可能被未知数更改的变量
定义一个只读的 int 类型的变量,并且编译器每次都去内存中取值,不做优化
小结:
·const 变量具有只读属性
·const 不能定义真正意义上的常量
·const 将具有全局生命周期的变量存储于只读存储区
·volatile 强制编译器减少优化,必须每次从内存中取值
狄泰软件学院课堂笔记