今天的一个问题!达人解答!

gzliaojian 2008-10-24 07:20:42
int* ptr;
const int a=9;
ptr=(int*)&a;
*ptr=19;
printf("%d\n%d\n",*ptr,a);

输出结果是 19,9

疑问:
1.为什么可以修改&a地址的内容;
2.同一个地址(ptr和&a一样),为什么(*ptr<>a)
...全文
344 39 打赏 收藏 转发到动态 举报
写回复
用AI写文章
39 条回复
切换为时间正序
请发表友善的回复…
发表回复
gzliaojian 2008-10-29
  • 打赏
  • 举报
回复
这个问题还是没有一个结果!
我觉得没有解决...
还是结了哦
once_and_again 2008-10-29
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 fengogo 的回复:]
1. &a 是 const int*, 你强制转换成了 int * , 所以可以修改*ptr
2. 可能是编译时编译器用常数替换了a . 试一下用这个声明:volatile const int a=9;
[/Quote]不知道啊,学习了。
firtre 2008-10-29
  • 打赏
  • 举报
回复
学习了
gzliaojian 2008-10-27
  • 打赏
  • 举报
回复
恩~似乎理解了!
还是有许多疑问!~

....
const int a=10;//放在只读数据区域?
void main(void )
{
const int b=11;//不放在只读数据区域??
...
}
这个说法对吗?
dfkjsdhfks 2008-10-27
  • 打赏
  • 举报
回复
貌似还有一个麻烦的问题,在VC 6.0上const int a=10写在main函数里没问题,而写在主函数外的话,编译没问题,但运行不了,会提示出错,这个问题不能用所谓的"常量折叠"来解释,真的是只读与非只读区域的问题,如果是的话好像与"常量折叠"又有冲突,因在"常量折叠"里面是不会在定义的时给常量a分配空间的啊,它们之间会有什么联系吗.
l176266956 2008-10-26
  • 打赏
  • 举报
回复
26楼和32楼说得真好.
bfhtian 2008-10-26
  • 打赏
  • 举报
回复
学习
dfkjsdhfks 2008-10-26
  • 打赏
  • 举报
回复
26楼的基本上正确,我还想补充一下,常量一般是不分配空间的,26楼也提到过这一点,取地址后才会强制分配,所以它确实只有一个地址,应该不存在什么"原来的常量的地址".
这个"常量折叠"是在编译器进行语法分析的时候,将常量表达式计算求值,并用求得的值来替换表达式,放入常量表。可以算作一种编译优化
因为编译器在优化的过程中,会把碰见的const全部以内容替换掉(跟宏似的: #define PI 3.1415,用到PI时就用3.1415代替),这个出现在预编译阶段;但是在运行阶段,它的内存里存的东西确实改变了!!!但当你只调用a时,它不会去读地址,除非你显式去调用地址.如果你加上一句cout << *(int *)&a <<endl;的话,你将得到19.
如果这种理解没问题的话,这个问题应该可以画上句号了.
太乙 2008-10-25
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 baihacker 的回复:]
C/C++ codeconst volatile int a=9;
[/Quote]

so easy




6: int* ptr;
7: const int a=9;
00414F18 mov dword ptr [ebp-8],9//存入 a
8: ptr=(int*)&a;
00414F1F lea eax,[ebp-8]//取地址
00414F22 mov dword ptr [ebp-4],eax
9: *ptr=19;
00414F25 mov ecx,dword ptr [ebp-4]//取ptr指向的地址
00414F28 mov dword ptr [ecx],13h//存入
10: printf("%d\n%d\n",*ptr,a);
00414F2E push 9//注意,看这里!!!!!!!!!!!!!!
00414F30 mov edx,dword ptr [ebp-4]//ptr
00414F33 mov eax,dword ptr [edx]//
00414F35 push eax
00414F36 push offset string "%d\n%d\n" (0042c9fc)
00414F3B call printf (00415160)
00414F40 add esp,0Ch




sujita 2008-10-25
  • 打赏
  • 举报
回复
你的这解释好像真的行啊,因为如果写一句a=a+1;它显示的错误就是l-value specifies const object 而如果把const int a=9写到main 函数里面的话程序会运行不了,学习了.希望高手再来确定一下.让大家学习学习.
baihacker 2008-10-25
  • 打赏
  • 举报
回复
const volatile int a=9; 
visame 2008-10-25
  • 打赏
  • 举报
回复
If you cast away the constness of an object that has been explicitly declared as const, and attempt to modify it, the results are undefined.
visame 2008-10-25
  • 打赏
  • 举报
回复

The following demonstrates the use of the const_cast operator:

#include <iostream>
using namespace std;

void f(int* p) {
cout << *p << endl;
}

int main(void) {
const int a = 10;
const int* b = &a;

// Function f() expects int*, not const int*
// f(b);
int* c = const_cast<int*>(b);
f(c);

// Lvalue is const
// *b = 20;

// Undefined behavior
// *c = 30;

int a1 = 40;
const int* b1 = &a1;
int* c1 = const_cast<int*>(b1);

// Integer a1, the object referred to by c1, has
// not been declared const
*c1 = 50;

return 0;
}
/*
The compiler will not allow the function call f(b). Function f() expects a pointer to an int, not a const int. The statement int* c = const_cast<int>(b) returns a pointer c that refers to a without the const qualification of a. This process of using const_cast to remove the const qualification of an object is called casting away constness. Consequently the compiler will allow the function call f(c).

The compiler would not allow the assignment *b = 20 because b points to an object of type const int. The compiler will allow the *c = 30, but the behavior of this statement is undefined. If you cast away the constness of an object that has been explicitly declared as const, and attempt to modify it, the results are undefined.

However, if you cast away the constness of an object that has not been explicitly declared as const, you can modify it safely. In the above example, the object referred to by b1 has not been declared const, but you cannot modify this object through b1. You may cast away the constness of b1 and modify the value to which it refers.
*/
wudeshou82666 2008-10-25
  • 打赏
  • 举报
回复
学习到了
visame 2008-10-25
  • 打赏
  • 举报
回复

Const cast
Sometimes, you have a const variable and you really want to pass it into a function that you are certain won't modify it. But that function doesn't declare its argument as const. (This might happen, for instance, if a C library function like strlen were declared without using const.) Fortunately, if you know that you are safe in passing a const variable into a function that doesn't explicitly indicate that it will not change the data, then you can use a const_cast in order to temporarily strip away the const-ness of the object.

Const casts look like regular typecasts in C++, except that they can only be used for casting away constness (or volatile-ness) but not converting between types or casting down a class hierarchy.

// a bad version of strlen that doesn't declare its argument const
int bad_strlen (char *x)
{
strlen( x );
}

// note that the extra const is actually implicit in this declaration since
// string literals are constant
const char *x = "abc";

// cast away const-ness for our strlen function
bad_strlen( const_cast<char *>(x) );

Note that you can also use const_cast to go the other way--to add const-ness--if you really wanted to.
visame 2008-10-25
  • 打赏
  • 举报
回复
*ptr=19;----->Dangerous
gzliaojian 2008-10-25
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 gzliaojian 的回复:]
引用 5 楼 lunarfan 的回复:
(int*)&a强制类型转换本来就产生一个临时的值,所以ptr并不等于&a,可以自己调试。

但是它们确实是一个地址啊!

第2个问题从各位朋友的总结来说就是优化的问题!

第1个问题const int a=9
它的汇编代码应该是
.section .rodata
.align 4
.type a,object
.size a,4
a:

[/Quote]
查资料知道!c和c++编译器会把const定义的外部变量放在只读数据.而我估计是本题出现的问题是因为,不是外部变量就不放在只读数据...我的理解!不知道对不!
gzliaojian 2008-10-25
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 lunarfan 的回复:]
(int*)&a强制类型转换本来就产生一个临时的值,所以ptr并不等于&a,可以自己调试。
[/Quote]
但是它们确实是一个地址啊!

第2个问题从各位朋友的总结来说就是优化的问题!

第1个问题const int a=9
它的汇编代码应该是
.section .rodata
.align 4
.type a,object
.size a,4
a:
.long 9
是放在只读区域吧!.rodata


这是一道笔试题!

hgcwhz 2008-10-25
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 baihacker 的回复:]
C/C++ codeconst volatile int a=9;
[/Quote]
这样输出的结果就是19,19了。


int* ptr;
const int a=9;
0041262E mov dword ptr [a],9
ptr=const_cast<int*>(&a);
00412635 lea eax,[a]
00412638 mov dword ptr [ptr],eax
*ptr=19;
0041263B mov eax,dword ptr [ptr]
0041263E mov dword ptr [eax],13h
printf("%d\n%d\n",*ptr,a);
00412644 mov esi,esp
00412646 push 9
00412648 mov eax,dword ptr [ptr]
0041264B mov ecx,dword ptr [eax]
0041264D push ecx
0041264E push offset string "%d\n%d\n" (41B8ACh)


int* ptr;
const volatile int a=9;
0041262E mov dword ptr [a],9
ptr=const_cast<int*>(&a);
00412635 lea eax,[a]
00412638 mov dword ptr [ptr],eax
*ptr=19;
0041263B mov eax,dword ptr [ptr]
0041263E mov dword ptr [eax],13h
printf("%d\n%d\n",*ptr,a);
00412644 mov esi,esp
00412646 mov eax,dword ptr [a]
00412649 push eax
0041264A mov ecx,dword ptr [ptr]
0041264D mov edx,dword ptr [ecx]
0041264F push edx
lizhengc 2008-10-25
  • 打赏
  • 举报
回复
1.为什么可以修改&a地址的内容;
因为你把它强制转换为int *类型了,虽然原来是const的,但强制转换后就不一样了。这个问题Bruce Eckle在他的《c++编程思想 第一卷》中的常量一章中讨论过,我记得对于这种情况他的评论为:虽然c++有助于防止错误的发生(指类型检查),但程序员自己打破这种安全机制,那它也是无能为力的。
2.同一个地址(ptr和&a一样),为什么(*ptr <>a)
这里ptr和&a不是完全一样的,一般c++不会为常量分配内存空间,而是通过常量折叠的方式处理。但在程序中如果取了常量的地址,那么就会强制c++为其分配内存,这里又不能打破常量不能被改变的限制,所以后来强制为其分配的空间和原来的常量已经不是同一个地址了。如下汇编代码:
381: const int a=9;
00410FCB mov dword ptr [ebp-0CCh],1
382: int *ptr=(int *)&a; //通过强制类型转换把const int -->int *
00410FD5 lea ecx,[ebp-0CCh]
00410FDB mov dword ptr [ebp-0D0h],ecx
383: *ptr=19;
00410FE1 mov edx,dword ptr [ebp-0D0h]
00410FE7 mov dword ptr [edx],0Bh
可见原来的a地址为ebp-0CCh,ptr的为ebp-0D0h,两个是不一样的。
加载更多回复(19)

64,660

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧