鱼C论坛

 找回密码
 立即注册
查看: 4078|回复: 25

[技术交流] 谁说const变量不能改变吗?我就改变给你看

[复制链接]
发表于 2013-9-16 19:47:47 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
大家学习C语言,在用const修饰一个变量后,改变量的值一般就不能改变了,是一个只读变量。
当你用赋值语句对你定义的这个变量赋值时,编译会报错的。
但是,我可以通过scanf函数,来达到修改const修饰只读变量的数值。希望知道这其中的原理的同学来进行讨论。

下面是我测试的代码,各位发表下自己的见解吧!


  1. #include <stdio.h>

  2. int main()
  3. {
  4.       const int MAX = 10;
  5.       printf("%d\n", MAX);

  6.       // MAX = 100;    此处,用赋值语句报错,但是用scanf函数给定数值就不报错

  7.       scanf("%d", &MAX );        //修改const变量MAX的值
  8.       printf("%d\n", MAX);

  9.       return 0;
  10. }
复制代码

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2013-9-16 21:39:35 | 显示全部楼层
通过修改const变量的地址确实是可以改变const变量的值,怎么修饰,都是变量,你的方法就是通过地址去改变了这个变量的值!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 0 反对 1

使用道具 举报

 楼主| 发表于 2013-9-17 02:15:56 | 显示全部楼层

深夜睡不着,来讨论下。
你说的这个是不对的,我朋友也是这么说的,经过我调试,修改数值后,const变量的地址还是没有改变,奇了怪了,呵呵!
希望大家踊跃来讨论啊!!!

以下是测试代码:
  1. #include <stdio.h>

  2. int main()
  3. {
  4.       const int MAX = 10;
  5.       printf("%d\n", MAX);
  6.       printf("&MAX = %x\n", &MAX);        //未改变前地址

  7.       // MAX = 100;    此处,用赋值语句报错,但是用scanf函数给定数值就不报错

  8.       scanf("%d", &MAX );        //修改const变量MAX的值
  9.       printf("%d\n", MAX);
  10.       printf("&MAX = %x\n", &MAX);        //改变后地址

  11.       return 0;
  12. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-9-17 03:47:18 | 显示全部楼层
scanf("%d", &MAX );  &MAX 是作为一个指针 仅代表内存地址; 执行这句的时候,是对对应内存地址里的值进行修改,与const无关.
  相当于: max ->00104000 (10)  
               scanf("%d", 00104000 )    %d 替换 10
可以做个试验,const一个变量a   再定义一个普通变量b    使&a和&b相等  
再通过修改b的值 看看a的值能否也同时发生变化?   试一下 我没试过 不懂编程...
               
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-9-17 07:31:45 | 显示全部楼层
moria 发表于 2013-9-17 03:47
scanf("%d", &MAX );  &MAX 是作为一个指针 仅代表内存地址; 执行这句的时候,是对对应内存地址里的值进行 ...

经过测试,你说的方法行不通。
在编译&MAX = &b是,出现错误:不能将'int *' 到 'const int',如果将b改成const,那么b也不能通过赋值语句来改变它的值。

这个估计需要深入scanf函数内部了,希望小甲鱼能来为我们答疑解惑!!!同意的同学来顶贴啊:lol:

下面是测试代码:
  1. #include <stdio.h>

  2. int main()
  3. {
  4.       const int MAX = 10;
  5.       int b = 5;
  6.       &max = &b;   //这句报错
  7. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-9-17 09:05:03 | 显示全部楼层
awen162 发表于 2013-9-17 02:15
深夜睡不着,来讨论下。
你说的这个是不对的,我朋友也是这么说的,经过我调试,修改数值后,const变量的 ...

修改地址里面的变量的值,变量的地址是使用的周期内众生不变,你还没理解这个吧,都没理解我说的意思!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-9-17 15:54:23 | 显示全部楼层
不想说了,用事实说话吧。
把代码分析发上来,一起研究和讨论,谢谢!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-9-17 19:09:18 | 显示全部楼层
本帖最后由 moria 于 2013-9-17 19:25 编辑
awen162 发表于 2013-9-17 15:54
不想说了,用事实说话吧。
把代码分析发上来,一起研究和讨论,谢谢!!

现学几句c语言.. 这段代码证明了  scanf函数 是直接修改内存地址指向的值
  1. #include <stdio.h>

  2. int main()
  3. {
  4.       const int MAX = 10;
  5.       int* a ; int c;
  6.       c = 80;                //通过修改普通变量c的值 达到控制const变量的目的
  7.       printf("%d\n", MAX);  // 显示为10
  8.       a = &MAX;               // max内存地址取出
  9.       *a = c;                    // 直接对max内存地址付值
  10.       printf("%d\n", MAX);  //显示为80
  11.       
  12.       printf("%d\n", &MAX);  //&MAX与指针a 指向同一内存单元
  13.       printf("%d\n", a);
  14.       printf("%d\n", &c);
  15.       

  16. }      
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-9-17 19:49:10 | 显示全部楼层
awen162 发表于 2013-9-17 07:31
经过测试,你说的方法行不通。
在编译&MAX = &b是,出现错误:不能将'int *' 到 'const int',如果将b改 ...

你直接用&max=&b当然不行
在定义max和b的时候,两个变量的地址已经分配好了,不能再改变的,况且max是变量,&max不是变量,不能作为左值。
要试验4楼的想法,应该如下:
const int max=10;
int *pb=&max;
scanf("%d",pb);
printf("\n%d",*pb);
---------------------
这代码我没测试,但如果你一楼代码可以的话,这段代码应该也没有问题。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-9-17 19:56:08 | 显示全部楼层
楼主逗了。没理解指针的概念吧?
  1. #include <stdio.h>

  2. int main()
  3. {
  4.       const int MAX = 10;
  5.       int b = 5;
  6.       &max = &b;   //这句报错 《= 你这句干什么?
  7. }
复制代码
&max = &b; 姑且认为是&MAX = &b;
你可知道&variable 表达式的返回值是什么不? 是地址值,是右值,是不可以直接赋值的。这可不是指针。
就算是int* a = &MAX;也是非法的。不知道你用的什么编译器,这玩意也没报错?
int* a = (int *)&MAX;是可以的,显式的强制转换是与C++ 中const_cast<>()转换一样,编译器会认为你知道这样使用的后果。不推荐这种用法。
只要你获得地址,你就可以修改地址指向的数据。const只是一种限定,强制约束程序行为的语法规则而已。你可以用很多方法绕过去,就像law一样。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-9-17 22:26:36 | 显示全部楼层
应该跟内存存储的位置有关吧,若将const变量定义在全局,则该变量存储在只读区域,同时此变量
不可以修改,而按照楼主的写法,将const变量定义在局部,该变量是存储在栈区的,所以可以通过那种方法修改。
楼主可以试试,将const变量写在外面(全局),应该是不可以修改的。会报错的。
我在linux下试了下,报错了,无法修改。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-9-17 23:27:34 | 显示全部楼层
谁说不能改变的,拖出去打死!const在C语言里修饰的是只读变量。只是通知编译器在编译时发现有改变只读变量的值时就报错,但是通过间接改变内存的方法修改只读变量的值是很OK的!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-9-18 07:37:40 | 显示全部楼层
本帖最后由 awen162 于 2013-9-18 07:45 编辑

谢谢各位的讨论,让我明白和清晰了很多。尤其是8楼-11楼的朋友分析的很透彻,感谢!!!
再说下11楼朋友说的,我调试了下,局部变量可以修改const定义变量的值,而当定义const变量为全局变量是,编译和连接都可以,运行时出现不能为读的错误,应该就是不能修改了。学到知识了:ton:

通过各位的解释,以及万能的网络,我引用下别人的解释可能会更加清楚的明白C/C++中const的一些用法。我很感谢各位
c语言中const修饰的常量并不是一个真正的常量,你可以把它当做一个不可修改的变量,他有自己的内存空间。虽然不可以通过变量来修改值,但是可以通过变量地址来修改,即const int a;中a是const的,但是a的地址不是const的。例如C语言中
const int a = 5;
int array[a];会报错,他把a当做了变量来处理,但是在c++中不会报错。c++中a视为常量,C++中的const常量并不放在内存中,而是有自己的常量表。只有当你用到&a时才会为常量分配内存。在c++中修改常量的地址常量值是不会改变的,因为当遇到常量是他会到常量表中查找,而不会到内存中读取。


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-9-18 09:05:32 | 显示全部楼层
你若真是要改变const类型变量,我推荐你用C++新风格类型转换 const_cast<>(const)。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

头像被屏蔽
发表于 2013-9-18 14:53:44 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-9-18 16:55:42 | 显示全部楼层
给力啊。。。。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-7-16 19:45:21 | 显示全部楼层
c++ primer原文大概意思是这样.

指向常量的指针,仅仅要求不能通过改变该指针的值改变对象的值,而没规定不能通过其他途径修改

常量指针,指针本事是个常量.并不表示不能通过指针修改其所指对象的值


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-7-16 21:27:46 | 显示全部楼层

  1. #include <stdio.h>

  2. int main()
  3. {
  4.       const int MAX = 10;
  5.       printf("%d\n", MAX);

  6.       // MAX = 100;    此处,用赋值语句报错,但是用scanf函数给定数值就不报错

  7.           printf("&MAX = %x\n", &MAX);        //未改变前地址

  8.           int *p = (int*)&MAX;
  9.           *p = 123;

  10.       //scanf("%d", &MAX );        //修改const变量MAX的值
  11.       printf("%d\n", MAX);
  12.            printf("&MAX = %x\n", &MAX);        //改变后地址
  13.           
  14.       return 0;
  15. }
复制代码


我测了一下,发现编译是可以通过
但是MAX的值是修改不了的,呵呵
vc6.0  亲测
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-7-16 22:20:40 | 显示全部楼层
LZ已经找到正确答案了,各位测试人员应该先看看LZ最后的结论。
测试人员中,凡是以.c作为源文件的(C语言),都是可以改变const值的,凡是以.cpp作为源文件的(C++语言),都是不能改变const值的。

C语言里的const int a = 2;中的const只是说明不能通过a来改变该变量的值,可以通过其它方式来改变。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2017-5-31 12:18:44 | 显示全部楼层
每一个变量都有其地址    常量也不例外   你到一条街上的5号房   请他吃顿饭  让你的朋友进这间房子

不就是改变了这个房子里的人吗   地址不会变  变的是值
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-3-29 21:01

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表