C语言中常量保证变量不被修改的方法有哪些

  介绍

小编给大家分享一下C语言中常量保证变量不被修改的方法有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获、下面让我们一起去了解一下吧!

在C语言中,常量是如何保证变量不被修改的?

<强>我们可以想到两种方式:

第一种,由编译器来阻止修改const变量的语句,让这种程序不能通过编译,

第二种,由操作系统来阻止,即把常量的内存地址访问权限标记为“只”读,一旦运行中的程序试图修改它,就会产生异常,终止进程。

上面想到的这两种方式,都能达到让某一变量的值不被修改的目的,那么究竟是哪一种呢?我们写两个例子来看一看。

先来看一个简单的例子,源文件const。c:

# include  & lt; stdio.h>   const  int =10;   int  main ()   {   ,int  * p=,;   ,printf(“初始:% d \ n", a);   ,* p=1;   ,printf(“修改:% d \ n", a);   ,return  0;   }

编译,会收到一个警告:

美元gcc - o const1 const1.c
const。c:在函数的主要# 39;:
const。c: 7:12:警告:初始化丢弃’const # 39;从指针目标类型限定符[-Wdiscarded-qualifiers]
,,,,int * p=,,

忽略之,运行程序:

美元。/const1最初
:
10段错误(信息转储)

运行出错了,报错是“段错误”,即“段错误”,它是在提醒我们,程序中用错误的权限访问了内存某区域。这说明,操作系统把变量一个美元加载到了一段只读内存区域之中,因此对该区域地址的写操作将引发异常,这是由操作系统的内存保护机制决定的。

也就是说,在这段程序里,const的只读属性是由操作系统来实现的,而不是由编译器来实现的(编译器只抛出了警告,并没有阻止编译通过)。

这对吗?不完全对,我们来看另一个例子,源文件const2。c:

# include  & lt; stdio.h>   int  main ()   {=10,const  int ;   ,int  * p=,;   ,printf(“初始:% d \ n", a);   ,* p=1;   ,printf(“修改:% d \ n", a);   ,return  0;   }

编译,还是收到同样的警告:

美元gcc - o const2 const2.c
const。c:在函数的主要# 39;:
const。c: 12:警告:初始化丢弃’const # 39;从指针目标类型限定符[-Wdiscarded-qualifiers]
,,,,int * p=,,

忽略之,运行程序:

。/const2
初始:10
修改:1

<强>咦?怎么成功运行了,而且一个的值还被顺利修改了?

结合以上两个例子,我们可以得出以下推测:

const只是C语言中的一种对变量的修饰符,例子中的一种,与其说是“常”量,不如说是“不打算修改的变量”。它只是语法上的一种声明,它的作用就是告诉编译器”我不想修改它”,因此编译器会从语法上检查程序中是否有修改它的语句(例如“=1;”),一旦发现这种“违背初衷”的语句,就会报错阻止你。

然而,编译器所阻止的仅仅是对这一个符号对应值的修改而已,却并不阻止对这个地址的值的修改,源文件“const2.c”之所以能顺利通过编译且正常运行,就是因为它利用一个名字不叫一个的指针指向它,从而绕过了编译器的语法检查。

打个比方,周树人的笔名叫鲁迅,警察只知道要抓鲁迅,这时候他就可以用一句“你们抓鲁迅跟我周树人有什么关系?”来骗过他们。

从这个角度来说,const的作用是靠编译器仅仅从语法检查来实现的,因此存在运行时的漏洞。

<强>那么为什么“const1.c”就不能正常运行呢?

仔细看这两个源程序,区别仅仅在于,在“const1.c”中,一个被声明为全局变量,而在“const2。c”中,它被声明为主要函数中的一个局部变量。全局变量与局部变量的区别在于,前者会在程序开始运行之前就被加载,加载后会一直留在内存中,且加载的位置在数据区,直到程序退出;后者只有在运行到它时才会被加载,且加载的位置是运行时的栈帧,一旦超出作用于就会被回收。

因此,编译器会对被声明为全局变量的const int一进行优化,把它放到只读内存区内,这一内存区的权限是“阅读\>以上是“c语言中常量保证变量不被修改的方法有哪些”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

C语言中常量保证变量不被修改的方法有哪些