我想知道以下如何工作@编译器级别。
int const iVal = 5;
(int&)iVal = 10;
一些m / c或编译器级别的答案会非常充实。
提前致谢。
答案 0 :(得分:8)
在第一行中定义一个常量整数。从此以后,在你的程序中,允许编译器只用值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;