如何利用指针改变const类型的值

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何利用指针改变const类型的值相关的知识,希望对你有一定的参考价值。

我以前用过的,可以

但现在忘了

向高手求助,谢谢!
是能够的。
改变后可以通过变量名直接访问该值。

但不是这样。
没有借助其他的关键词。

我当时做的仅仅是把const int *(举例而已)转换成int *等做法,并没有涉及到其他更多的语句。
当时的印象是,就是用了几个*号和几个括号把类型强制转换了一下(或者几下)。

但现在我忘了如何转化的。

我用

const int a=4;
*(int *)&a=5;
这样的不行。
没有错,但是a的值也没有变化。

当时好像用了几层括号。

请C++爱好者、高手们继续帮个忙~
提高悬赏了~~~

同时请解释之:

#include <iostream>
using namespace std;
void main()

const int a=3;
int *p=(int *)&a;
*p=6;
cout << *p << '\t' << p << endl
<< a << '\t' << &a << endl;


p指向的内存地址就是a的内存地址,但为什么还是不行呢?
注:如果是char类型的好像有问题,需要转化为void*类型

再次提高悬赏了~~~~~~~~

#include <iostream>
using namespace std;
void main()

const int a=10;
cout<<a<<endl;
int *q=(int*)(&a);
int t=(int)a;
int *p=&t;
*p=6;
*q=5;
cout<<a<<endl;
cout<<*q<<endl;
cout<<*p<<endl;


看看这个程序把,然后下断点,调试下,调试的过程中你会发现用指针访问的是表示修改了,但是变量名的依然还是原来的值..
其实,你应该知道一点,使用了强制转换的地方,最后都为它对应生成了一个临时变量,这个时候,指针也指向了这个临时变量,然后你用指针修改仅仅修改了的都是这些临时变量的值,并没有作用到const变量a,因此,你通过指针输出是改变了的值,但是通过变量名则还是原来的值

所以说,你以前所做的修改仅仅是停留在临时变量上的修改(就是假修改,误导了你认为自己修改了const类型的值),对于const类型的变量,你是永远也不能修改的,否则,定义const就没有安全性可言了

现在应该知道为什么了把...如果还有问题
可以发消息给我

晕...还是同一个帖子,看错了
刚调试了下,的确是改了,但是可能就是const的作用把,至于为什么,我现在也不得而知,可能不能很好的帮到你

补充:首先,收回上面的回复...上面的回复是错的
最后修改下,给个权威答案
#include<stdio.h>
int main()

const int a=3;
int *p=(int *)&a;
*p=6;
printf("%d\t%d\n", *p , p );
printf("%d\t%d\n", a , &a );
return 0;

你把它分别放到C++编译器上和C编译器上运行这段代码看看结果如何.如果你用C++编译器编译上述代码,那么这个问题的原因是编译器在编译时自动优化了const值,造成你的code变成 printf("%d\t%d\n", 3 , &a );
我在这里瞎插一句把,感觉就有点像#define N 10
然后用10替换了N的意味把,虽然这样说不准确
但就这样理解把,的确是可以修改,只是编译器优化的缘故而导致输出的和想象的不一样了

这就是权威答案,如果你学过汇编,你可以上汇编试试
如果你用C语言编译器,你会发现,输出的都是6,因为C语言编译器并没有对它进行优化

底下是汇编代码:

INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES

CONST SEGMENT
$SG3833 DB '%d', 09H, '%d', 0aH, 00H
ORG $+1
$SG3834 DB '%d', 09H, '%d', 0aH, 00H
CONST ENDS
PUBLIC _main
EXTRN _printf:PROC
; Function compile flags: /Odtp
_TEXT SEGMENT
_a$ = -8 ; size = 4
_p$ = -4 ; size = 4
_main PROC
; File c:\documents and settings\hwp\桌面\test.cpp
; Line 3
push ebp
mov ebp, esp
sub esp, 8
; Line 4
mov DWORD PTR _a$[ebp], 3
; Line 5
lea eax, DWORD PTR _a$[ebp]
mov DWORD PTR _p$[ebp], eax
; Line 6
mov ecx, DWORD PTR _p$[ebp]
mov DWORD PTR [ecx], 6
; Line 7
mov edx, DWORD PTR _p$[ebp]
push edx
mov eax, DWORD PTR _p$[ebp]
mov ecx, DWORD PTR [eax]
push ecx
push OFF
SET $SG3833
call _printf
add esp, 12 ; 0000000cH
; Line 8
lea edx, DWORD PTR _a$[ebp]
push edx
push 3
push OFFSET $SG3834
call _printf
add esp, 12 ; 0000000cH
; Line 9
xor eax, eax
; Line 10
mov esp, ebp
pop ebp
ret 0
_main ENDP
_TEXT ENDS
END

看到了没有....这里
; Line 8
lea edx, DWORD PTR _a$[ebp]
push edx
push 3
push OFFSET $SG3834
call _printf
add esp, 12 ; 0000000cH

直接是push 3
意思说直接输出的是数值3而不是变量值
参考技术A 利用const_cast
例如:
const int m = 1987;
int *p = const_cast<int *>(&m);

然后利用*p就可以改变了m的值了。。。

PS: 刚才测试了下,是不能修改,汗颜了
大二的时候用C++内嵌汇编写过一个intel的CPUID,练习的是定义用一个类的const成员来接受EAX返回值是可以的,正如楼上所说的,还以为普通成员也可以,刚才想了下,其实类或者结构体的这种情况也是有据可考的,举个例子如
class CPUCore
public:
CPUCore():m_ebx(1987)
DWORD m_eax;
const DWORD m_ebx;
DWORD m_ecx;
DWORD m_edx;
;
CPUCore cpuCore;
cout<< &cpuCore << endl << &cpuCore.m_eax << endl << &cpuCore.m_ebx << endl << &cpuCore.m_ecx << endl << &cpuCore.m_edx;

会发现运行结果是:
0013FF54
0013FF54
0013FF58
0013FF5C
0013FF60
也就是在程序运行时在内存分配上并没有把static storage area、stack、heap分开,而仅仅是在类内部自己划分开来,所以相对与整个程序来说m_ebx仍然是stack,所以可以通过类外的指针修改。类中的const仅仅是编译器限制的一个行为。在内存分配上和非const并没有区别。
放在stack中是有原因的,应为一个类可以定义出很多不同对象的,而每个对象中的const成员值又是不同的,其实这种情况完整等效应该是static const成员,这样无论定义几个类都是这一个成员,也就自然应该到static storage area中了

而函数体内的定义就不是这样了,是先划分一块static storage area存放所有static成员,不依赖与声明顺序,然后是static,再是heap,当然三者顺序取决于编译器。
参考技术B const的常量是不能被修改的,要是能修改不就失去了他的意义了吗

常用const可以提高代码的效率和健壮性,可谓是好处多多啊
参考技术C 2楼的方法是不能更改m的值的!

const int m = 1987;
int *p = const_cast<int *>(&m);
*p=1988;
cout<<m<<ends<<*p<<ends<<*(&m)<<endl;
输出结果为 1987 1988 1987

这是为什么呢?

理由只能是编译器在栈上另外分配了空间而指针p就是指向该空间的,所以i值仍然无法更改(当然你仍然可以通过一天“非正当”方法来间接修改)。
但这只是针对普通变量而言的,对于结构体等复合变量就不一样了
例如:
struct strct

strct():i(1987)
const int i;
;
strct st;
int* ptr=(int*)&st.i;
*ptr=1988;
cout<<st.i<<endl;
这时候i的值就被更改了!
这是编译器的特性。
参考技术D 真的可以改变吗`?反正我是没这样做过,网上找了一下试验了以下,
似乎没有一个能做到,估计跟编译器有关吧。
这个是网上有人讨论这个问题的,或许有点用吧:
http://topic.csdn.net/t/20051130/16/4428952.html

const与指针

一、指向常量的指针

定义:const 变量类型 *变量;

例如

      const double pi=3.14;///////pi是个常量,它的值不能改变

      double *ptr=&pi;//////错误:ptr是一个普通指针,可以改变ptr所指对象的值,而pi是个常量

      const double *cptr=&pi;/////正确:cptr指向一个双精度常量

     *cptr=42;//////错误:*cptr指向的是常量,不能给*cptr赋值

      注意:指针的类型必须与其所指对象的类型一致,但是有两个例外。第一种例外情况是允许指向常量的指针指向一个非常量对象:

      double dval=3.14;

      cptr=&dval;/////正确:但是不能通过cptr改变dval的值

      和常量引用一样,指向常量的指针也指向一个变量。仅仅要求不能通过该指针改变对象的值,而没有规定那个对象的值不能通过其他方式改变。

二、常量指针

定义:变量类型 *const 变量名;

例如

     int errNumb=0;

     int * const curErr=&errNumb;/////curErr将一直指向errNumb

     const double pi=3.14;

     const double * const pip=&pi;/////pip是一个指向常量对象的常量指针

注意:常量指针必须初始化,而且一旦初始化完成,则它的值(也就是存放在指针中的那个地址)就不能再改变。

以上是关于如何利用指针改变const类型的值的主要内容,如果未能解决你的问题,请参考以下文章

C++ const 学习

c语言中const 是啥意思,怎么用,啥时候用?

2015042120150422指针数组

指针和const

const与指针

const关键字总结