2009-03-19 3 views
0

私は以下のことが@コンパイラレベルでどのように動作するのか知りたかったのです。これは内部的にどのように動作するかint const iVal = 5; (int&)iVal = 10;

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

m/cまたはコンパイラレベルの回答が多額になります。

ありがとうございます。

+0

ちなみに構文は同じが、しかし、のようなものでachivedことができた(私の知る限り)有効C.ではありません "(&をint型)"、この質問は "C" でタグ付けされていますが、最初の行にiValのタイプを指定する必要があります。 –

+0

構文が間違っています - タイプはiVal宣言にはなく、(int&)は無効です(少なくともCでは)。 – qrdl

+0

お嬢さん。:)ありがとうIraimbilanja :) – mahesh

答えて

8

undefined behaviorです。

最初の行では、定数を定義します。これからプログラムでは、コンパイラはiValを値5で置き換えることができます。代わりにメモリからロードすることはできますが、それは利点がありません。

2番目の行は、メモリ位置に、コンパイラから数値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 
4

あなたのcown ompilerで実行してassember出力を見てみませんか?

+0

ニール、VC7はそれをすべてコンパイルします。それはデバッグモードでもそれを完全に実行します。リリースモードでは、iVal値は変更されません。 – sharptooth

+0

何も理由なしにダウン投票されたために上書きされました。この投稿は多くの意味があります.OPが本当に知っている(疑問がある)コードコンパイラが生成するものを知りたければ、コンパイラの出力を逆アセンブルするのが最良の方法です。 – qrdl

+0

これは未定義の動作なので、異なるコンパイラでは異なることが許されます.1つのコンパイラの結果は比較的無駄です。 – snemarch

5

Cスタイルのキャストはconst_castとして機能します。あなたがそうするために起こると、コンパイラはIVALの実際のメモリを割り当てるしないことを決定した場合は、

const_cast<int&>(iVal) = 10; 

を書いた場合と同じように、あなたは未定義の動作に実行します。

例えば、VC7はそれをすべてコンパイルします。それはデバッグモードでもそれを完全に実行します。リリースモードでは、iValの値は割り当て後も変更されません。それは5のままです。

このようにしないでください。

1

これは、「const-ness」の考え方が言語/コンパイラにのみ存在するために可能です。実際のコンピュータメモリでは、すべてが可変です。コードがコンパイルされると、iVal変数は単にRAM内の場所になります。

edit:上記は、定数が実際にメモリに置かれていることを前提としています。 sharptooth's answerを参照してください。 Cスタイルのキャストを使用して

は、それが簡単な整数の変数であるかのように、このメモリ位置を扱い、10

+0

「これは機能しますか?あんまり! –

+0

良い点。私は言葉を変更します。 –

+0

コンパイラはconstを読み込み専用メモリセグメント(OSがサポートしている場合)に置くことができるため、言語の問題だけではありません。 – qrdl

0

未定義の動作にその値を設定するようにコンパイラに指示します。

リリースビルドでは、ほとんどのコンパイラがconst値を直接置き換えますが、になります。メモリ負荷がかかる場合があります。また、2番目の割り当ては、プラットフォームとコンパイラによって、アクセス違反を生成する場合と生成しない場合があります。 Iircインテルのコンパイラはconstデータを読み取り専用メモリに格納するため、実行時にアクセス違反が発生します。

0

これが組み込みシステムだった場合、iValはフラッシュに格納される可能性が高いため、書き込むことは効果がありません。

しかし、埋め込みコンパイラは一般に、メモリの特定の領域が読み込み可能であるかどうかを追跡していないので、コンパイラはこれをエラーと見なさない可能性があります。

リンカーは通常、リンカーがiValが定数であると判断するので、リンカーを通過する可能性があると考えます。しかし、iValの使用方法を決定するのはリンカーの仕事ではありません。

int *Ptr = (int *) &iVal; 
*Ptr = 10; 
関連する問題