内部如何工作int const iVal = 5; (int&)iVal = 10;

时间:2009-03-19 08:47:24

标签: c++ c compiler-construction

我想知道以下如何工作@编译器级别。

int const iVal = 5; 
(int&)iVal = 10; 

一些m / c或编译器级别的答案会非常充实。

提前致谢。

6 个答案:

答案 0 :(得分:8)

undefined behavior

在第一行中定义一个常量整数。从此以后,在你的程序中,允许编译器只用值5替换iVal。它可以从内存中加载它,但可能不会,因为这不会带来任何好处。

第二行写入编译器告诉你的内存位置包含数字5.但是,这不能保证有任何效果,因为你已经告诉编译器该值不会改变。

例如,下面将定义一个 5 元素的数组,并打印一个未定义的值(或者它可以做任何想做的事!它是未定义的)

int const iVal = 5;
(int&)iVal = 10;
char arr[iVal];
cout << iVal;

生成的程序集可能类似于:

sub ESP, 9      ; allocate mem for arr and iVal. hardcoded 5+sizeof(int) bytes
                ; (iVal isn't _required_ to have space allocated to it)
mov $iVal, 10   ; the compiler might do this, assuming that you know what
                ; you're doing. But then again, it might not.
push $cout
push 5
call $operator_ltlt__ostream_int
add ESP, 9

答案 1 :(得分:5)

C风格的强制转换充当const_cast。就像你写的那样

const_cast<int&>( iVal ) = 10;

如果您碰巧这样做并且编译器决定不为iVal分配实际内存,则会遇到未定义的行为。

例如,VC7编译好了。它甚至可以在调试模式下运行。在发布模式下,分配后iVal值不会改变 - 它仍为5.

所以你不应该这样做。

答案 2 :(得分:4)

为什么不通过自己的编译器运行它并查看汇编程序输出?

答案 3 :(得分:1)

这是可能的,因为“const-ness”的概念仅存在于语言/编译器中。在实际的计算机内存中,一切都是可变的代码编译完成后,iVal变量就是RAM中的一个位置。

编辑:上面假设常量实际上放在内存中。请参阅sharptooth's answer

使用c样式转换告诉编译器将此内存位置视为一个简单的整数变量,并将该值设置为10.

答案 4 :(得分:0)

未定义的行为。

在发布版本中,大多数编译器会直接替换const值 - 但是可以运行到一个执行内存加载的编译器。此外,第二个分配可能会也可能不会生成访问冲突,具体取决于平台和编译器。 Iirc Intel的编译器将const数据放入只读内存中,因此会在运行时生成访问冲突。

答案 5 :(得分:0)

如果这是一个嵌入式系统,iVal很可能会存储在flash中,因此写入它不会有任何影响。

但是,编译器可能不会将此视为错误,因为嵌入式编译器通常不会跟踪特定的内存区域是否可读。

我怀疑它也可能会传递链接器,因为链接器通常会确定iVal是常量,因此闪存中也是如此 - 但确定如何使用iVal并不是链接器的工作。

顺便提一下,这个问题用“C”标记,但“(int&amp;)”语法不是(AFAIK)有效C.然而,同样可以用以下内容来实现:

int *Ptr = (int *) &iVal;
*Ptr = 10;