BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / cpp / #51684同步于 2011/4/26
CPP机器人发帖

[合集] 求大牛:const 在c语言中是怎么实现其只读特性的?

shenlei
2011/4/26镜像同步0 回复
☆─────────────────────────────────────☆ dyrdyr (么儿) 于 (Mon Apr 11 13:31:19 2011) 提到: RT 针对“const变量不可改变,即便是通过地址也不可变”做了如下测试: const int n = 9; printf("%d ",n); int *p = (int*)(&n); const int *a = &n; *p = 5; int m = n; int t = *p; printf("%d ",*(p)); printf("%d ",*(a)); printf("%d ",*(&n)); printf("%d ",n); printf("%d ",m); 打印的结果是: 9 5 5 9 9 9 跟踪显示,n的存储地址通过*p = 5已经变成5,n的地址也没变,但是m=n 之后,m还是等于9。。。 9是哪来的啊? 各种不解。。。求大牛。。 更奇怪的结果。。。。。。。。 更多不解。。 { int x = 9; const int n = x; printf("%d ",n); int *p = (int*)(&n); const int *a = &n; *p = 5; int m = n; int t = *p; printf("%d ",*(p)); printf("%d ",*(a)); printf("%d ",*(&n)); printf("%d ",n); printf("%d ",m); } printf("\n"); { const int n = 9; printf("%d ",n); int *p = (int*)(&n); const int *a = &n; *p = 5; int m = n; int t = *p; printf("%d ",*(p)); printf("%d ",*(a)); printf("%d ",*(&n)); printf("%d ",n); printf("%d ",m); } 打印的结果是: 9 5 5 5 5 5 9 5 5 9 9 9 ☆─────────────────────────────────────☆ iam19891211 (【洛阳亲友如相问】 【就说我在学六楼】) 于 (Mon Apr 11 14:34:49 2011) 提到: const在编译时会被编译为静态成员,它确定于编译时期,属类型级,通过类型来访问。 百度的 ☆─────────────────────────────────────☆ a206206 (右将军府副手) 于 (Mon Apr 11 14:52:42 2011) 提到: c的const和c++的不一样 ☆─────────────────────────────────────☆ dyrdyr (么儿) 于 (Mon Apr 11 15:50:49 2011) 提到: 谢谢啦。不过还是不太明白。。。[em17][em17] 【 在 iam19891211 的大作中提到: 】 : const在编译时会被编译为静态成员,它确定于编译时期,属类型级,通过类型来访问。 : 百度的 ☆─────────────────────────────────────☆ liaowang11 (Bill) 于 (Mon Apr 11 15:57:56 2011) 提到: 貌似在.rodata里面, 映射到内存中为只读? ☆─────────────────────────────────────☆ zxsword (小绝) 于 (Mon Apr 11 16:08:34 2011) 提到: 这个应该不是吧。。。 如果是运行时才能确定值的(例const int m=n,n不是编译时可知的一个值),怎么都不可能放到.rodata的。。。 【 在 liaowang11 的大作中提到: 】 : 貌似在.rodata里面, 映射到内存中为只读? : -- ☆─────────────────────────────────────☆ times123 (每天写一个helloworld喵) 于 (Mon Apr 11 16:27:28 2011) 提到: 同样的代码,在我的系统中是9 5 5 5 5 5 C中的const,无责任推测,是编译器的概念,编译时,如果有任何对const符号的赋值行为,都无法通过编译。 C中的const变量,在内存中并没有任何特殊的地方,如果得到const的地址,可以更改地址中的值,如代码所示。 gcc编译,-Wall,但还是并没有任何warning。 至于楼主的测试结果,猜测是编译器的优化所致,嗯。 ☆─────────────────────────────────────☆ times123 (每天写一个helloworld喵) 于 (Mon Apr 11 16:38:21 2011) 提到: gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) 开启-O2结果为:9 5 5 9 9 9 不开启-O2结果为:9 5 5 5 5 5 我了个去,也不用去看汇编代码了。。。就是编译器优化代码的缘故。编译器故做聪明,在int m=n时,并没有从内存中读取n的值,直接把n当做常量处理了,就是这样。 ------------------- zx@zx-laptop:~$ gcc -o t -Wall -O2 t.c zx@zx-laptop:~$ ./t 9 5 5 9 9 9 5 zx@zx-laptop:~$ zx@zx-laptop:~$ gcc -o t -Wall t.c zx@zx-laptop:~$ ./t 9 5 5 5 5 5 5 //多添了一行打印t值的代码。。。int t = *p; 就是打印这个t值的代码。打印这个t值,基本上就是答案了。 ☆─────────────────────────────────────☆ dyrdyr (么儿) 于 (Mon Apr 11 16:44:28 2011) 提到: 但是,百度面试的时候,面试官告诉我,const不管通过什么方式都能改变,即便是通过地址也不行。。。所以才引发了我对这个东西的探索。 如果真是编译器优化的结果,那这是什么一个优化原则呢? 【 在 times123 的大作中提到: 】 : 同样的代码,在我的系统中是9 5 5 5 5 5 : C中的const,无责任推测,是编译器的概念,编译时,如果有任何对const符号的赋值行为,都无法通过编译。 : C中的const变量,在内存中并没有任何特殊的地方,如果得到const的地址,可以更改地址中的值,如代码所示。 : ................... ☆─────────────────────────────────────☆ times123 (每天写一个helloworld喵) 于 (Mon Apr 11 17:01:54 2011) 提到: =。=并不是说百度的面试官说的都是对的,他也是人,也能犯错,不是吗? const不能改变的是C++,但C和C++还是有一些区别的。 代码说明了这个问题,嗯。 可以加-g选项读汇编代码。 printf("%d ",*(p));//自然打印5了。 printf("%d ",*(a));//自然打印5了。 printf("%d ",*(&n)); //如果优化的话,*(&n)=。=,首先优化成n,n又是个const常量,然后没从内存中读取n。。。这个值比较特殊,是编译时就已经确定了的值。 printf("%d ",n);//打印n,没从内存中读取n,而是编译器已经知道n为9 printf("%d ",m);//m等于n,同样没从内存中读取n呗,这次读取被编译器优化掉了。 printf("%d ",t); //这个就得从内存中读取值了。打印的值,就是5,嗯 开启高优化级别后,优化掉一次内存读取,就是这样。n值是编译时可知的,那么这个n的符号,可直接用字面值常量'9'代替.编译器维护一个表格,当需要n时直接查表,不就优化掉一次内存访问了吗? 【 在 dyrdyr 的大作中提到: 】 : 但是,百度面试的时候,面试官告诉我,const不管通过什么方式都能改变,即便是通过地址也不行。。。所以才引发了我对这个东西的探索。 : 如果真是编译器优化的结果,那这是什么一个优化原则呢? : 【 在 times123 的大作中提到: 】 : ................... ☆─────────────────────────────────────☆ dyrdyr (么儿) 于 (Mon Apr 11 17:06:07 2011) 提到: 那加了优化之后,系统把“9”放到哪里去了呢。。另外找了一个地方存放n原来的值? 你这么说来,const变量是可以通过地址改变。。那就是百度的那个面试官错了。。 【 在 times123 的大作中提到: 】 : gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) : 开启-O2结果为:9 5 5 9 9 9 : 不开启-O2结果为:9 5 5 5 5 5 : ................... ☆─────────────────────────────────────☆ times123 (每天写一个helloworld喵) 于 (Mon Apr 11 17:13:19 2011) 提到: 楼主的代码是有一些特殊的。const n值是编译时可知的。 所以,在开启编译器优化选项后,很可能就优化掉了对n这个对象的内存读取。举个不太合适的例子,就像编译器对待define常量类似。 但对代码稍微更改之后: int x; scanf("%d",&x); const int n = x;此时n值不再是编译时可知了,此时编译器便没有办法优化掉对n值的内存访问了。 -------------------- 代码结果为: zx@zx-laptop:~$ gcc -o t -Wall t.c zx@zx-laptop:~$ ./t 7 7 5 5 5 5 5 5 zx@zx-laptop:~$ gcc -o t -Wall -O2 t.c t.c: In function ‘main’: t.c:6: warning: ignoring return value of ‘scanf’, declared with attribute warn_unused_result zx@zx-laptop:~$ ./t 7 7 5 5 5 5 5 5 开启更高的优化级别: zx@zx-laptop:~$ gcc -o t -Wall -O3 t.c t.c: In function ‘main’: t.c:6: warning: ignoring return value of ‘scanf’, declared with attribute warn_unused_result zx@zx-laptop:~$ ./t 7 7 5 5 5 5 5 5 -------------------------------- 结论,帖子中出现的怪异现象,是因为编译器的优化所致。编译器对编译时已知的常量进行了优化。如果n值编译时不可知,就不会存在类似的现象了。 另,楼主本来的问题是c中的const对象。C中的const,无责任推测,是编译器的概念,编译时,如果有任何对const符号的赋值行为,都无法通过编译。C中的const变量,在内存中并没有任何特殊的地方,如果得到const的地址,可以更改地址中的值,如代码所示。 ☆─────────────────────────────────────☆ dyrdyr (么儿) 于 (Mon Apr 11 17:14:17 2011) 提到: 受教了。。谢谢。。 我说可以,百度的面试官,反问了我一句,“那他为什么还要叫常量呢?”。。呵呵,原来如此。。 c++中,const不能改变,你测试了? 【 在 times123 的大作中提到: 】 : =。=并不是说百度的面试官说的都是对的,他也是人,也能犯错,不是吗? : const不能改变的是C++,但C和C++还是有一些区别的。 : 代码说明了这个问题,嗯。 : ................... ☆─────────────────────────────────────☆ dyrdyr (么儿) 于 (Mon Apr 11 17:23:31 2011) 提到: 怎么好像有点不对啊。 代码为: int x = 9; const int n = x; 时, 打印的结果是: 9 5 5 5 5 5 这个结果是没有被优化的, 跟你那个加了scanf的结果一样。 这个。。。。 【 在 times123 的大作中提到: 】 : 楼主的代码是有一些特殊的。const n值是编译时可知的。 : 所以,在开启编译器优化选项后,很可能就优化掉了对n这个对象的内存读取。举个不太合适的例子,就像编译器对待define常量类似。 : 但对代码稍微更改之后: : ................... ☆─────────────────────────────────────☆ times123 (每天写一个helloworld喵) 于 (Mon Apr 11 17:25:34 2011) 提到: 不用存储“9”呀。。。类似define常量的方式=。= 严格的说,应该是C的const变量是可以通过地址来改变的。 【 在 dyrdyr 的大作中提到: 】 : 那加了优化之后,系统把“9”放到哪里去了呢。。另外找了一个地方存放n原来的值? : 你这么说来,const变量是可以通过地址改变。。那就是百度的那个面试官错了。。 : 【 在 times123 的大作中提到: 】 : ................... ☆─────────────────────────────────────☆ dyrdyr (么儿) 于 (Mon Apr 11 17:36:55 2011) 提到: 哦,是呀。。2了。。[em17] 【 在 times123 的大作中提到: 】 : 不用存储“9”呀。。。类似define常量的方式=。= : 严格的说,应该是C的const变量是可以通过地址来改变的。 ☆─────────────────────────────────────☆ zxsword (小绝) 于 (Mon Apr 11 17:38:06 2011) 提到: 在这样的代码中,n值就并不是编译时可知了。你是用一个变量初始化了n。 那自然和我写的scanf的版本的结果一样了。 【 在 dyrdyr (么儿) 的大作中提到: 】 : 怎么好像有点不对啊。 : 代码为: : int x = 9; : ................... ☆─────────────────────────────────────☆ dyrdyr (么儿) 于 (Mon Apr 11 17:45:41 2011) 提到: 恩,我理解了,大大的谢谢啦。。 【 在 zxsword 的大作中提到: 】 : 在这样的代码中,n值就并不是编译时可知了。你是用一个变量初始化了n。 : 那自然和我写的scanf的版本的结果一样了。 ☆─────────────────────────────────────☆ zxsword (小绝) 于 (Mon Apr 11 17:47:40 2011) 提到: 我是C++菜鸟=。= 刚才试了一下。 cpp中: int *p=&n;这个肯定不能通过,类型不符,编译时错误。 int *p=reinterpret<int *>(&n); 这个依旧不能通过=。= int *p=(int *)&n; *p=5; 通过编译,顺利改变n的值。继承自c的语法,更改了const n。 看来,C++中,const变量,也不过是一个普遍的内存对象。const特性,应该是通过编译时的强大的类型检查来保证的。 因为根据C++的语法,是无法获得一个指向const对象的非const指针的。通过编译时的类型检查,可以肯定程序中没有一个非const指针能够指向const对象,也就保证了const特性。 【 在 dyrdyr 的大作中提到: 】 : 受教了。。谢谢。。 : 我说可以,百度的面试官,反问了我一句,“那他为什么还要叫常量呢?”。。呵呵,原来如此。。 : c++中,const不能改变,你测试了? : ................... ☆─────────────────────────────────────☆ dyrdyr (么儿) 于 (Mon Apr 11 18:18:14 2011) 提到: 汗,没学过C++。。。谢谢啦。。 【 在 zxsword 的大作中提到: 】 : 我是C++菜鸟=。= : 刚才试了一下。 : cpp中: : ................... ☆─────────────────────────────────────☆ cangtian (AlexandreSongBillong) 于 (Mon Apr 11 19:00:03 2011) 提到: 如果是全局变量const int a=5;存在于.rodata中,int *b=&a;*b=6;会提示段错误 ☆─────────────────────────────────────☆ astrophile (候鸟) 于 (Mon Apr 11 19:53:08 2011) 提到: 【 在 zxsword 的大作中提到: 】 : 那自然和我写的scanf的版本的结果一样了。 那个times123是马甲? ☆─────────────────────────────────────☆ astrophile (【还我艾神】) 于 (Mon Apr 11 20:13:52 2011) 提到: 【 在 liaowang11 的大作中提到: 】 : 貌似在.rodata里面, 映射到内存中为只读? : -- 如果是全局的const变量,或者同时用static和const修饰,则在.rodata里。而楼主例子里n这个局部变量,是分配在栈上的,即使用const修饰也是可以改变的,只要能编译通过(而c++里编译器会报错)。 ☆─────────────────────────────────────☆ renne (歼灭天使 玲) 于 (Mon Apr 11 20:14:50 2011) 提到: const不能改变的是c++ 这句话也值得商榷吧…… const int n = 9; int *p = (int*)(&n); 单凭这两句话,有啥c++ c的区别吗……vs2008的结果是n一样改了 【 在 times123 (每天写一个helloworld喵) 的大作中提到: 】 : =。=并不是说百度的面试官说的都是对的,他也是人,也能犯错,不是吗? : const不能改变的是C++,但C和C++还是有一些区别的。 : 代码说明了这个问题,嗯。 : ................... ☆─────────────────────────────────────☆ renne (歼灭天使 玲) 于 (Mon Apr 11 20:15:17 2011) 提到: lz这代码vs2008能过…… 【 在 astrophile (【还我艾神】) 的大作中提到: 】 : 如果是全局的const变量,或者同时用static和const修饰,则在.rodata里。而楼主例子里n这个局部变量,是分配在栈上的,即使用const修饰也是可以改变的,只要能编译通过(而c++里编译器会报错)。 ☆─────────────────────────────────────☆ zxsword (小绝) 于 (Mon Apr 11 20:18:05 2011) 提到: 我不懂C++额。。。 那段代码是用g++编译的,我就当是cpp了=。=对于cpp的认识,目前就局限在将后缀.c改为.cpp的阶段。。。 我是面试被鄙视了好多次的纯C++菜鸟[em9] 【 在 renne 的大作中提到: 】 : const不能改变的是c++ 这句话也值得商榷吧…… : const int n = 9; : int *p = (int*)(&n); : ................... ☆─────────────────────────────────────☆ zxsword (小绝) 于 (Mon Apr 11 20:27:18 2011) 提到: 额。。。秘密的小马甲被发现了。。。 【 在 astrophile 的大作中提到: 】 : : 那自然和我写的scanf的版本的结果一样了。 : 那个times123是马甲? : -- : ................... ☆─────────────────────────────────────☆ zxsword (小绝) 于 (Mon Apr 11 20:47:16 2011) 提到: 突然想到,全局中的const变量,是编译时可知的值呀。那么编译器采用一定的优化技术,是可能被编译器优化掉的。 如果单个的源文件,这个const变量用define常量替换掉,也是毫无问题的。 代码中任何需要用到const常量的地方,都可以在汇编代码中用 立即数 来代替。如此,便省去了一次的内存读操作。 那么const变量的意义在哪里呢? 无责任推测,如果有多个源文件的话,更改一个define常量的话,所有用到的这个define常量的文件,全部需要重新编译。而在.rodata段中的const 变量,并没有define常量这个缺点,只需要重新编译有const变量的那个源文件即可,然后众多需要用到这个const常量的cpp文件,只需要读.rodata段中的一个常量,和之前一模一样。 随意乱想了想,唔。 【 在 astrophile 的大作中提到: 】 : : 貌似在.rodata里面, 映射到内存中为只读? : : -- : 如果是全局的const变量,或者同时用static和const修饰,则在.rodata里。而楼主例子里n这个局部变量,是分配在栈上的,即使用const修饰也是可以改变的,只要能编译通过(而c++里编译器会报错)。 : ................... ☆─────────────────────────────────────☆ txmm (你被tx啦!) 于 (Mon Apr 11 20:57:39 2011) 提到: 这楼好热啊 ☆─────────────────────────────────────☆ astrophile (【还我艾神】) 于 (Mon Apr 11 22:34:24 2011) 提到: 有道理 【 在 zxsword 的大作中提到: 】 : 突然想到,全局中的const变量,是编译时可知的值呀。那么编译器采用一定的优化技术,是可能被编译器优化掉的。 : 如果单个的源文件,这个const变量用define常量替换掉,也是毫无问题的。 : 代码中任何需要用到const常量的地方,都可以在汇编代码中用 立即数 来代替。如此,便省去了一次的内存读操作。 : ................... ☆─────────────────────────────────────☆ ashley1901 (ashley) 于 (Mon Apr 11 22:40:54 2011) 提到: 大牛呀!!!! ☆─────────────────────────────────────☆ zzcc (Binux <足兆叉虫>) 于 (Mon Apr 11 22:49:27 2011) 提到: 所以说这些东西都是“定义”罢了,只要让它看起来是这样就好了,具体是怎么实现的,爱怎么实现就这么实现呗。 虽然不敢说这样理念不好,但是觉得如同python抛弃常量一样,既然能通过变量实现相同的功能,还要常量干嘛? 说常量是为了不能修改?python的做法是用同一的命名区分,比如全大写 如果你真的想改?如果你真的知道自己在干什么,这又何尝不可呢? 即使是第三方调用的时候别人尝试修改,如果他知道他自己在干什么,改坏了库的开发者为什么要为此负责?让他改去吧(因为有命名空间的存在,不存在误修改) 编程语言也是设计出来的,各有各的设计,不敢说哪个好,各有所好吧。。 ☆─────────────────────────────────────☆ dyrdyr (么儿) 于 (Tue Apr 12 12:58:55 2011) 提到: 你这个写法确实是会提示错误; 但是如果这样: int x; const int a = x; int _tmain(int argc, _TCHAR* argv[]) { x = 9; // x = 0; a = 0; 不知道这个0是随机给的,还是系统默认初始化全局变量为0; int *p = (int*)(&a); //x = 9;a = 0; *p = 5; // x = 9; a = 5; 所以,我无责任推测:全局的const初始化为常数的时候,放在.rodata中。 加个条件。 【 在 cangtian 的大作中提到: 】 : 如果是全局变量const int a=5;存在于.rodata中,int *b=&a;*b=6;会提示段错误 ☆─────────────────────────────────────☆ dyrdyr (么儿) 于 (Tue Apr 12 13:08:18 2011) 提到: 我觉得是不是const初始化为常数的时候,才会放到.rodata里头。如果不是,那还是可以改变的,只要编译通过。 【 在 astrophile 的大作中提到: 】 : 如果是全局的const变量,或者同时用static和const修饰,则在.rodata里。而楼主例子里n这个局部变量,是分配在栈上的,即使用const修饰也是可以改变的,只要能编译通过(而c++里编译器会报错)。 ☆─────────────────────────────────────☆ dyrdyr (么儿) 于 (Tue Apr 12 13:19:50 2011) 提到: 全局的const也可以是编译未知的啊。。 比如: int x; const int n = x; ps:弱弱的。。你的那个推测没怎么看明白。。[em17][em17]。。能解释下吗?不好意思。。 【 在 zxsword 的大作中提到: 】 : 突然想到,全局中的const变量,是编译时可知的值呀。那么编译器采用一定的优化技术,是可能被编译器优化掉的。 : 如果单个的源文件,这个const变量用define常量替换掉,也是毫无问题的。 : 代码中任何需要用到const常量的地方,都可以在汇编代码中用 立即数 来代替。如此,便省去了一次的内存读操作。 : ................... ☆─────────────────────────────────────☆ zxsword (小绝) 于 (Tue Apr 12 14:04:47 2011) 提到: 先解释一下我的那些推测,再稍微更正一下。所有的推测,应该建议在已初始化的const变量的基础上。 推测建立在已初始化的const变量和define常量的基础上,比较了define和const变量的意义。 【 在 dyrdyr 的大作中提到: 】 : 全局的const也可以是编译未知的啊。。 : 比如: : int x; : ................... ☆─────────────────────────────────────☆ times123 (每天写一个helloworld喵) 于 (Tue Apr 12 14:34:02 2011) 提到: 尝试了一些代码,如下: int x; const int n; const int m=9; int main() { printf("%d",n); x=9; int *p=(int *)&m; // int *p=(int *)&n; *p=5; printf("%d",n); printf("%d",*p); putchar('\n'); return 0; } 以elf格式为例,依赖于实现,不同的平台可能会有所不同: 更改m值时,段错误,验证了已初始化的const变量确实是在.rodata中。 而未初始化的变量,并不是在.rodata段中的,而是在.bss中,在程序装入内存时,以0填充这些未初始化的变量,这也就是说默认值为0。 喵了个咪的,未初始化的const变量也是未初始化的变量,也在.bss中。既然在.bss中,只要我们能够获得地址,那么就能更改存储于这个地址的对象了,.bss段是可读可写的。更改n值成功打印5。 综述一下:如果能够获得const对象的指针且该指针的属性不是指向const,而const对象的存储位置并非.rodata,例如栈中或者.bss中,那么const变量的值,是可改的。如果能够获得地址,且该地址不是在只读的内存段,那么就可以改变地址中的值。很多内存错误,也正是来源于此,例如缓冲区溢出,呵呵。 至于楼主的主贴的代码,神奇的现象是由于编译器故做聪明的bug。 哦,还有,这些都是一些琐碎的实现细节,没必要太过深入,语言终归是拿来用的。在实际的扣腚中,简洁明晰的代码,才是王道。 ☆─────────────────────────────────────☆ dyrdyr (么儿) 于 (Tue Apr 12 16:24:34 2011) 提到: 大赞。。谢谢啦。。。学习不少。。 可是面试总要问这些变态的问题。。莫有办法啊。。 【 在 times123 的大作中提到: 】 : 尝试了一些代码,如下: : int x; : const int n; : ................... ☆─────────────────────────────────────☆ DrJan ( DrJan) 于 (Tue Apr 12 17:10:06 2011) 提到: 楼主将帖子链接发给面试官 请求一下他指导 或者表明爱学习的态度 或者帮助他进步 = =! ☆─────────────────────────────────────☆ gootyking (『热情一顶乐团』团长|回帖终结者A1) 于 (Tue Apr 12 17:34:06 2011) 提到: 不错啊 【 在 DrJan ( DrJan) 的大作中提到: 】 : 楼主将帖子链接发给面试官 请求一下他指导 : 或者表明爱学习的态度 : 或者帮助他进步 : ................... ☆─────────────────────────────────────☆ xudi5566 (原本无罪) 于 (Tue Apr 12 20:38:02 2011) 提到: 我记得C 和 C++编译器对const的处理是不一样的。貌似在C里面const比较类似于readonly,只读不一定是不可修改的。而C++里的const就一定是常量。楼主的代码确实是可能把原来的 const int m=9; 地址的值改了。在程序的打印里不是从m原来的地址取值。而是直接输出了9. LZ可以试试在 const int m=9;前面加 violate 修饰符。这样应该就能改变了。 ☆─────────────────────────────────────☆ Under (小小黑@北邮刷天下) 于 (Tue Apr 12 22:57:51 2011) 提到: 在c++中 可以用 int * p = const_cast<int *>(&n); 来获得一个指向const对象的非const指针 【 在 zxsword 的大作中提到: 】 : 我是C++菜鸟=。= : 刚才试了一下。 : cpp中: : ................... ☆─────────────────────────────────────☆ Under (小小黑@北邮刷天下) 于 (Tue Apr 12 23:12:58 2011) 提到: 是volatile吧。。 【 在 xudi5566 的大作中提到: 】 : 我记得C 和 C++编译器对const的处理是不一样的。貌似在C里面const比较类似于readonly,只读不一定是不可修改的。而C++里的const就一定是常量。楼主的代码确实是可能把原来的 const int m=9; 地址的值改了。在程序的打印里不是从m原来的地址取值。而是直接输出了9. : LZ可以试试在 const int m=9;前面加 violate 修饰符。这样应该就能改变了。 : -- : ................... ☆─────────────────────────────────────☆ Under (小小黑@北邮刷天下) 于 (Tue Apr 12 23:15:19 2011) 提到: vs 2005中,const int n; 这句代码无法通过编译 提示必须初始化常量对象 不知道你是怎么通过编译的 【 在 times123 的大作中提到: 】 : 尝试了一些代码,如下: : int x; : const int n; : ................... ☆─────────────────────────────────────☆ astrophile (【还我艾神】) 于 (Wed Apr 13 11:28:07 2011) 提到: 【 在 Under 的大作中提到: 】 : vs 2005中,const int n; : 这句代码无法通过编译 : 提示必须初始化常量对象 不知道你是怎么通过编译的 : ................... 代码是c的话用gcc可以编译过,但c++的话用g++也会报错。 c和c++里const差别还挺多的。感觉c里面的const主要靠把变量放在.rodata段里实现,而c++里更多的是靠编译器来检查。 ☆─────────────────────────────────────☆ zhaojf30 (不明真相的群众) 于 (Wed Apr 13 16:11:58 2011) 提到: 【 在 times123 的大作中提到: 】 : 尝试了一些代码,如下: : int x; : const int n; : ................... 赞大牛,那请问如果const int n是在main()中定义的话,应该在.rodata段中还是在栈中呀? ☆─────────────────────────────────────☆ jokerlee (Jackal The Dire) 于 (Wed Apr 13 22:21:48 2011) 提到: 插一小段 const的只读属性是怎么实现的完全是编译器相关的,运行时的内存模型不是语言标准所约束的 const的作用仅仅是语法上的约定,编译器的义务仅仅是检查的语法上改变常量值的行为 编译器将程序装载时(或者说编译期)就能确定值的常量放到只读段里并不是其义务 所以楼主问“在c语言中是怎么实现其只读特性的?” 答案就是c/c++只保证编译期语法上的只读,不保证也无法保证运行时的只读 (就算是放到只读段里,你也可以通过底层的driver或者hack操作系统改变段属性或者直接操作内存,只要存储介质不是只读的) 顺便感慨一下 现在的一些C/C++面试题对不少人的语言学习造成了的误导(我也被误导了很久)。花大量时间研究内存模型、编译优化等语言的“阴暗角落”。那些东西除了拿来吹nb在基本上一点实用价值都没有,而事实上,一个月之后就会忘得一干二净连nb都吹不了了。。 ☆─────────────────────────────────────☆ snowleaves (这个……) 于 (Wed Apr 13 22:45:45 2011) 提到: c++的const 可以绕过去……
订阅后,新回复会通过你的通知中心匿名送达。
0 条回复
暂无回复 · 你可以订阅本帖等待新回复。