设为首页 加入收藏

TOP

C语言进阶:const和volatile
2018-05-04 06:06:53 】 浏览:184
Tags:语言 进阶 const volatile

const只读变量

const修饰的变量是可读的,本质上是变量。

const修饰的局部变量在栈上分配空间;

const修饰的全局变量在全局数据区分配空间;

const只在编译期有用,在运行期无用。

所以,本质上来讲,const修饰的其实不是常量,而是一个不能被改变的变量(不能出现在赋值符号的左边)。

在现代编译器中,修改const全局变量将导致程序崩溃。

注意:标准C语言编译器不会将const修饰的全局变量存储于只读存储区,而是存储于可修改的全局数据区,其值依然可以改变。

观察下面代码,体会const的作用:

#include
  
   

const int g_cc = 5; //全局变量存储于只读存储区

int main()
{
	const int cc = 1;  //在栈上分配空间
	
	printf("%d\n", cc);
	
	//cc = 2;
	
	int *p = (int *)&cc;
	
	*p=3;
	
	printf("%d\n", cc);
	
	printf("g_cc = %d\n", g_cc);
	
	//g_cc = 6; //error
	
	p = (int *)&g_cc;
	
	*p=7;  //在gcc中报段错误  (在BCC中不报错)
	
	printf("g_cc = %d\n", g_cc);
	
	return 0;
}
  

在不同的编译器中,对于全局的const变量,编译效果不同。

在现代的编译器中,对于const修饰的全局变量, 会将其编译进只读存储区,一旦出现对只读存储区的修改,就会直接报错。(早期的支持标准C的编译器支持对const修饰的全局变量通过指针进行修改)

但标准C语言只是将其定义为只读,不涉及存储区。

const修饰的static将会在只读存储区中存储。

#include 
  
   

const int g_array[5] = {0};

void modify(int* p, int v) //不能使用void* p,是左值
{
	*p = v;
}

int main()
{
	int const i = 0;
	const static int j = 1;
	int const arry[5] = {0};
	
	modify((int*)&i, 2);
	//modify((int*)&j, 3);  //error
	modify((int*)&array[0], 4);
	//modify((int*)&g_array[0], 5); //error
	
	printf("%d\n", i);
	printf("%d\n", j);
	printf("%d\n", array[0]);
	printf("%d\n", g_array[0]);
	
	return 0;
}
  

const 修饰函数参数表示函数体内不希望改变参数的值;

const 修饰的函数返回至表示返回值不可改变,多用于返回指针的情形。

观察下面代码,体会const修饰参数和返回值:

注意:C语言中的字符串字面量存储于只读存储区,在程序中需要使用const char*指针。

#include 
  
   

const char* f(const int i)
{
	i = 5;  //error   test.c:5: error: assignment of read-only location ‘i’
	
	return "will willing";  //字面量
}

int main()
{
	const char* p = f(0);    //注意此处对 p 的声明为const char*
	
	printf("%s\n", p);
	
	p[5] = '_';  //error  test.c:16: error: assignment of read-only location ‘*(p + 5u)’
	
	printf("%s\n", p);
		
	return 0;
}
  

Linux下使用Gcc编译代码,报错信息如代码注释所示。

现代的编译器在每次操作时,都会去优化操作,避免每次去内存中存取数据。

volatile可理解为“编译器警告指示字”,它告诉编译器必须每次去内存中取变量值。

volatile注意修饰可能被多个线程访问的变量,也可以修饰可能被未知因素更改的变量。

int obj=10;

int a=0;  int b=0;

a = obj;
sleep(100);  ????????????????//编译器在编译的时候发现obj没有被当做左值使用,
????????????????????????????//因此会“聪明”的直接将obj替换成10,而把a,b都赋值为10.
b = obj;

可是在实际的程序运行中,比如多线程或者出现中断,会在sleep(100)中修改obj的值,这个时候b的值就会与预期不一样。

const volatile int i=0;

上述语句中变量i具有什么样的特性?

存储在内存中(不让编译器优化);不能做左值。

编译器如何改变这个变量?

通过指针。

小结:

const使得变量具有只读属性,不能定义真正意义上的常量。(enum可以)

const将具有全局生命期的变量存储在只读存储区。

volatile强制编译器减少优化(多用于嵌入式和多线程编程),必须每次都从内存中取值。

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇教你编写c语言实现输入10个数按从.. 下一篇C语言基础语法 - 分号、空格

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目