C ++,const转换 [英] C++, Const casting

查看:95
本文介绍了C ++,const转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Q)一个地址如何存储相同数据类型的值.

代码如下:

Q) How one address can store tho values of same data type.

The code is as follows:

//Programe
#include<iostream>
void main()
{
    const int x = 10;
    int *p=(int*)&x;

    *p=20;

    std::cout<<"*p="<<*p<<"  p="<<p<<std::endl;
    std::cout<<" x="<<x<<" &x="<<&x<<std::endl;
}


//输出
* p = 20 p = 0013FF60
x = 10& x = 0013FF60
按任意键继续 . . .

//S/W详细信息
Visual Studio 2008
版本9.0

我很困惑,一个地址怎么会有两个值. !!!


//Output
*p=20 p=0013FF60
x=10 &x=0013FF60
Press any key to continue . . .

//S/W details
Visual Studio 2008
ver. 9.0

I am flumoxed that how can one address have two values. !!!
Any help is appricated.

推荐答案

嗯,很有趣!
因为x声明为const int,所以编译器将其与#define x 10相同,并将源代码中的每个"x"替换为值10.但是,似乎仍存在一个名为x的变量,可以将其修改为你示范.从编译器生成汇编代码可以确认这一点.

毫无疑问,了解C ++规范的人也许可以澄清这一点.
Hmm, an interesting one!
Because x is declared as const int the compiler treats it the same as #define x 10 and replaces every ''x'' in the source code with the value 10. However it appears that a variable called x still exists and can be modified as you demonstrate. Generating the assembly code from the compiler confirms this.

No doubt someone who understands the C++ specification may be able to clarify this.


您遇到的问题是,您正在执行该语言中未定义的操作.当您声明const时,您对编译器说的是我不会修改它".一旦您做了一些可能会通过指针指向修改的操作,所有的赌注都将关闭,您将陷入.... 鼓卷.... 不确定的行为.

因此,当您获取地址或对const对象的引用,然后尝试对其进行写操作时,几乎任何事情都可能发生.请记住,当执行强制转换时,您是在告诉编译器您更了解它,并且它应该按照您说的去做.这是编译器正在报仇,并告诉您啊,愚蠢的C程序员[1],您已经进入Bjarne的领域,感到他的嘲笑!"

C ++不像C.在C中创建const时,您的意思是创建变量,但使其只读".在C ++中,您说的是此名称是该值的别名".获取常量的地址也不同.在C语言中,您说的是给我该变量的地址,我想通过一个间接级别从中读取它".在C ++中,您说的是我想使用该值,好像它是一个真正的只读变量"(通常用于函数调用),并且编译器必须这样做.它会创建正确类型的临时文件并提供地址.因此,在C上将const转换为const变量时可能会在C中工作,但在C ++中进行操作时它是未定义的(即错误).

用C语言来表示,您正在做的是:

The problem you''ve got is that you''re doing something that''s undefined in the language. When you declare a const anything you''re saying to the compiler "I''m not going to modify this." As soon as you do something that might modify it through pointer chicanery all bets are off and you''re into the teritory of.... drum roll.... undefined behaviour.

So when you take the address or a reference to a const object and then try and write through it just about anything can happen. Remember that when you do a cast you''re telling the compiler you know better and it should do what you tell it. This is the compiler getting it''s revenge and telling you "Ah ha foolish C programmer [1], you have entered the domain of Bjarne, feel his mockery!!"

C++ isn''t like C. When you create a const in C you''re saying "make a variable but make it read only." In C++ you''re saying "This name is an alias for that value." Taking the address of a constant is different as well. In C you''re saying "give me the address of that variable, I want to read from it through a level of indirection." In C++ you''re saying "I want to use that value as if it were a real readonly variable" (usually for a function call) and the compiler obliges. It creates a temporary of the right type and gives you it''s address. So while casting away const on a const variable might work in C it''s undefined (i.e. bad) when you do it in C++.

To put that in C terms what you''re doing is:

const int x = 10;

int y = x;
int *p = &y;



除非您从未看到y.

顺便说一句,您是否做了类似的事情:



Except you never see y.

Incidentally had you done something like:

void set_to_20( const int *p )
{
    *const_cast<int *>( p ) = 20;
}

int main()
{
    const int x = 10;
    int y = 10;

    set_to_20( &x );
    set_to_20( &y );

    std::cout << x << '\t' << &x << std::endl;
    std::cout << y << '\t' << &y << std::endl;
}



您会看到可以安全地从& y删除const,因为它指的是非const int,但是不能从& x删除,因为没有可写的名为x的变量.

现在,您知道Microsoft的编译器发生了什么,不要依赖它.尽管MS在这里使用了一种相当传统的方式来解释标准,但是编译器可能会做其他事情,使您无所适从.一种是(例如)将临时文件保留在只读存储器中,并在尝试写入时使代码崩溃.

嗯反正这就是我在抽搐的余地.哦,还有几个要点...

-main在C和C ++中都返回一个int.如果没有,则可能发生任何事情.返回void仅对于希望编写可在多个编译器上编译的标准代码的程序员嘲笑是有用的,它没有其他实用程序.

-(int *)在1990年代如此-考虑您要进行的转换,并使用static_cast(转换兼容值),reinterpret_cast(将位放入新的模具中)或const_cast(删除const或volatile).

干杯,



[1]不要否认,接受const的地址并使用C样式强制转换是一种死胡同.而且,如果某个讲师或讲师告诉您惯用的C ++要求您退款.

PS:欧根(Eugen)在评论中说,您永远看不到y的地址.其实你会的.编译器说的就是x的地址.您看不到x的地址,因为x没有地址,它只是一个别名,这就是编译器创建y的原因.



you''ll see that you can safely cast away const from &y as it refers to a non-const int but not from &x as there is no variable called x to write to.

Now you know what''s going on with Microsoft''s compiler, don''t rely on it. While MS use a fairly orthodox way of interpreting the standard here but there are other things that a compiler might do that could sink you without a trace. One is (for example) sticking the temporary in read only memory and crashing your code when it tries to write.

Er, anyway. That''s me whittering on enough. Ooo, couple of more points...

- main returns an int in both C and C++. If it doesn''t then anything can happen. Returning void is only good for being mocked by programmers that want to write standard code that compiles on more than one compiler, it has no other utility.

- (int *) is so 1990s - consider what you want your cast to do and use either static_cast (converting compatible values), reinterpret_cast (fitting the bits into a new mould) or const_cast (removing const or volatile).

Cheers,

Ash

[1] Don''t deny it, taking addresses of consts and using C style casts are a dead giveaway. And if some lecturer or instructor is telling you that''s idiomatic C++ ask for your money back.

PS: Eugen said in a comment that you never see the address of y. Actually you do. It''s what the compiler says is the address of x. You can''t see the address of x because x hasn''t got an address, it''s just an alias which is why the compiler creates y.


这篇关于C ++,const转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆