c言語ではコンパイラの際、式が自動変換され違うものとなる?

1. 代表的な例:「文字列リテラル」の場合

char *s = "abc";

見た目では:

「文字列 "abc"s に代入している」

ように見えますが、
実際の内部的な意味はこう👇

"abc" という定数文字配列の 先頭アドレスs に代入している」

つまり、コンパイラはこれを次のように変換します:

const char temp[4] = {'a', 'b', 'c', '\0'}; // 静的メモリ上
char *s = &temp[0];

表面の式と、メモリで起きていることが全然違うんです。


⚙️ 2. 配列の例でも同じ現象

int a[3] = {1, 2, 3};
int *p = a;

一見:

「a を p に代入している」

ように見えますが、
実際の意味は:

「配列 a の 先頭要素のアドレス(&a[0]) を p に代入している」

コンパイラは内部でこう変換します👇

int *p = &a[0];

🧠 3. C言語は「式を変換して最適化する」言語

Cは「式の見た目」よりも、「メモリ操作の意味」に忠実です。
だから、あなたの見ている a[i]"abc" は、
実際には別の形に解釈されます👇

見えている式コンパイラが読む「本当の式」意味
a[i]*(a + i)配列要素アクセス
"abc"&("abc"[0])リテラルの先頭アドレス
p[i]*(p + i)ポインタ演算
*p++*(p++)値を読み取りつつアドレスを進める
x = y + z;実際には「アドレスから値をレジスタにロードして加算してストア」メモリアクセス命令群

⚡ 4. なぜこんな仕組みになっているのか

Cの目的は、「人間が読めるアセンブリ」を作ることでした。
したがって:

設計目的結果
人間には高級に見せるa[i]"abc" のような表記を許す
機械的には効率的にするコンパイラがアドレス演算に自動変換する
可読性よりも最適化省略や暗黙変換を多用する

🔬 5. 図で見る "abc" の真相

char *s = "abc";

【あなたが見ているイメージ】

s = "abc";

【実際のメモリの構造】

静的領域:
 0x1000: 'a'
 0x1001: 'b'
 0x1002: 'c'
 0x1003: '\0'

スタック:
 s → 0x1000  ← このアドレス値が代入される

つまり:

  • "abc" 自体は 配列
  • でも式中では そのアドレス(定数値) に変換される
  • 結果、s には アドレス(ポインタ値) が入る

⚖️ 6. Cの根本思想:「表面は高級、動作は低級」

Cのコードは人間向けの文法をしているけれど、
コンパイラがそれを「アドレスと値の操作」に自動変換してくれる。

言語設計の考え方
Python「人間が理解しやすいこと」が最優先
Assembly「CPUが理解しやすいこと」が最優先
C言語「CPUが理解できる構造を、人間が読める形にした」

✅ まとめ

観点内容
表面上の式人間向けの抽象的な記法(例:a[i], "abc", x = y + z;
実際の意味メモリ操作+アドレス演算(例:*(a+i), &("abc"[0])
目的人間が書きやすく、CPUが理解しやすい中間言語的設計
結果「見た目と本当の動作が違う」=Cの特徴であり強み

🧠 一言でまとめると:

💡 C言語は“人間が書けるアセンブリ”。

見えている式は高級っぽいが、
内部ではすべて「アドレス計算」と「メモリアクセス」に展開されている。

だから「見えている式」と「本当の式」が違うのです。

\ 最新情報をチェック /

コメント

PAGE TOP
タイトルとURLをコピーしました