const 、volatile、const volatile int i = 0和 const与指针
前言
主要参考狄泰软件学院唐老师的《C语言进阶剖析班》
一、const 和 volatile
1.const 修饰的变量是只读的,本质还是变量。
2.const 修饰的局部变量在栈上分配空间。
3.现代编译器将 const 修饰的全局生命期的变量存储于只读存储区。
4.const 只对编译器有用,它告诉编译器,这个变量是只读的,不能对其进行左值操作,运行时没用。
5.const 使得变量具有只读属性。
6.const 不能定义真正意义上的常量。(C语言中只有枚举定义的是真正意义上的常量)
7.volatile 可理解为“编译器警告指示字”。
8.volatile 告诉编译器每次从内存中去取变量值。
9.volatile 主要修饰可能被多个线程访问的变量。
10.volatile 也可修饰可能被未知因素改变的变量。
11.volatile 强制编译器减少优化,必须每次从内存中取值。
二、示例
1.示例代码
编译器为GCC
#include <stdio.h>
const int a = 2;
int main()
{
const int b = 1;
int* p = (int *)&b;
printf("b = %d\n",b); //结果显示为1
//b = 3; //这里会报错 提示b是一个只读变量不能够被修改
*p = 3;
printf("b = %d\n",b); //结果显示为3 说明b不是一个真正意义上的常量,只是一个read only的只读变量。
p = (int*)&a;
printf("a = %d\n",a); //结果显示为2
//a = 4; //这里会报错 提示a是一个只读变量不能够被修改
//*p = 4; //报段错误,说明const 修饰的全局生命期的只读变量保存在只读存储区。
printf("a = %d\n",a);
}
#include <stdio.h>
const int g_array[5] = {0};
void modify(int* p, int v)
{
*p = v;
}
int main()
{
int const i = 0;
const static int j = 0;
int const array[5] = {0};
modify((int*)&i, 1); // ok
//modify((int*)&j, 2); // error j具有全局生命周期,存储于只读存储区
modify((int*)&array[0], 3); // ok
//modify((int*)&g_array[0], 4); // error g_array数组具有全局生命周
printf("i = %d\n", i); //显示i = 1
printf("j = %d\n", j); //显示 j = 0
printf("array[0] = %d\n", array[0]); //显示array[0] = 3
printf("g_array[0] = %d\n", g_array[0]);
return 0;
}
#include <stdio.h>
const char* f(const int i)
{
i = 5;
return "Delphi Tang";
}
int main()
{
char* pc = f(0);
printf("%s\n", pc); //显示Delphi Tang
//pc[6] = '_'; //段错误 原因是f函数返回值类型是 const char*类型,应将char* pc = f(0)改为 const char* pc = f(0),此时编译时该行报错。
printf("%s\n", pc);
return 0;
}
const volatile int i = 0;
两个问题:
1.变量i具有什么样的特性?
2.编译器如何处理这个变量?
答:1.程序运行时每次从内存里面取值不做任何优化,i是一个只读变量不能出现在赋值号的左边。
2.编译器不对这个变量进行优化。
2.cosnt 和指针
需要记住cosnt具有右结合性。
const int* p; //const修饰int* ,p可变、p指向的内容不可变
int const* p; //const修饰int* ,p可变、p指向的内容不可变
int* const p; const修饰p ,p不可变、p指向的内容可变
const int* const p; //const修饰int*和p ,p不可变、p指向的内容不可变