右や左の旦那様

哀れなぎんしゃりにお恵みを

自由研究

C言語のポインタに関する補足説明

投稿日:

前回、C言語のポインタに関する解説記事を書きまして、そこそこの反響を貰うとともにいくつかの指摘を受けました。
前回の記事では幾つか「ウソではないけど真実と違う」記述がありまして、その点を補足としていくつか説明します。
今回、初学者向けではなく中級者以降の人でないとナンノコッチャ度が高いのでお付き合いください。

仕様と実装のごちゃまぜ

前回の記事で行った最も激しいダマシがこれです。
C言語とは仕様であり、実装はコンパイラに依存します

前回、暗黙的にgccを利用して実験をしており、特にアドレス周りの記述はLinuxの64bit環境を前提としたコーディングが成されています。
しかし、究極的にはポインタがメモリアドレスであることすら仕様には明記されていません
ポインタ=アドレス、というのは、一部のコンパイラが勝手に決めた仕様に他ならないわけです。

特に、現在ナマのC言語が求められる局面というのは、一部の低レイヤーな挙動を制御するシステムに限られます。
具体的にはマイコンであるとか、ハードウェアの組み込みソフトであるとか、ファームウェアであるとか、ミドルウェアであるとかです。
つまり、皆さんが普段触れているようなWebアプリやスマホアプリ、Windows用プログラムの大半はC言語では書かれていない。
もはやニッチな分野でしか使われない特殊言語な訳です。
で、特殊言語ゆえに、環境ごとに実装が大きく異なります
なので、「C言語」と一口に言っても、その実装は様々であり、もはや「特殊な実装である方が普通」と言っても過言ではないわけです。

「コンパイラ」を便利に使いすぎている

前回、「コンパイラ」という言葉に全てを任せ過ぎています。
実際、gccにおいて「コンパイラ」の役割は以下のように細分化できます。

  • プリプロセッサ(#includeなどの展開)
  • コンパイラ(アセンブリへの変換)
  • アセンブラ(アセンブリから機械語へ変換し、オブジェクトファイル(.o)を生成)
  • リンカ(オブジェクトファイルを束ねて実行可能ファイルを作成)

これらを全てまとめて「コンパイラ」と呼称してしまっているわけです。

まぁ実際、gccはコマンド一つでソースファイル(.c)を実行可能ファイル(.outとか.exe)にできるわけですし、初学者が上記の呼称を意識する必要はないんですが。中級者以降なら分けられているのは知っておかないといけませんね。

なので、全てを「コンパイラ」が決めているというのは、そこそこ強烈なウソなわけです。

物理メモリと仮想メモリの概念の省略

ぶっちゃけ、仮想メモリというのはOSの用意する機能であってC言語が意識するところではないです。

ただ、実際に緑と黒のゲジゲジに乗っているのは物理メモリであり、Linuxで実行するファイルでポインタが指すアドレスは仮想メモリであります。
そして前回の記事で書いた「0x7fffffffe494」とかいうアドレスは全て仮想メモリです。
なので実際は「0x7fffffffe494」という場所が物理メモリ上にあるわけではなく、プロセスが持つ仮想メモリ空間上のアドレスなわけです。
実際に利用するときにはOSによって物理メモリへのマッピングが行われますが、物理メモリ上のアドレスというのはそれこそ誰も気にする必要のないところです。脆弱性を突きたいわけでなければ。

スタック領域とかヒープ領域とかうんぬん

変数のアドレスの場所、というのは宣言の仕方によって変化します。
ローカル変数であれば基本的にスタック領域に置かれると思いますが、グローバル変数だったりstatic宣言されていたりするとスタックではない領域に置かれることもあるでしょう。その場合、OSのメモリマッピングに依存して場所が決まることになります。多分。

また、スタック領域が絶対的にアドレスを決め打ちできるという保証もありません。スタック内でのメモリ配置はコンパイラによって行われますが、スタック領域がどこに取られるか、というのは正直自分は詳しくないです。
メモリマップを見る感じだとvdsoがスタックの前後に入りがちですがどういう法則なのやら。
またmallocコマンド等でヒープ領域を動的に確保した場合、それこそ動的に確保しているのでアドレスがどこになるか、というのは完全に未知数です。

とにかく変数のアドレス参照は相対的に行われるので、絶対アドレスを指定した参照なんて普通やっちゃいけないです。

そのため、メモリのアドレスをコンパイラが決めている、というのはいろいろな意味でウソのある表現だったわけです。

おわりに

前回の記事はなんだかんだ初学者向けのため、「本当はこうだけどちょっとウソをついておこう」という記述がちらほらありました。
その辺ツッコミを入れている方が多く、みんなマジメに読んでいるんだなぁって思いました。
そういう人は既にポインタについて詳しいハズなので、たのしくツッコミを入れてもらえれば良いです。

また、プログラミング初学者の人はC言語なんてあえて触ろうとせず、他の言語からとっつく方があなたの身と健康のためになると、と言っておきましょう。

-自由研究

執筆者:


comment

メールアドレスが公開されることはありません。

関連記事

no image

あみだくじはどれぐらいランダムか

あみだくじ。 紙とペンがあればすぐに作ることができるお手軽な抽選方法として知られています。 なにか物事を決めたいとき、あみだくじを使うという人も多いのではないでしょうか。 ふと思ったんですが、あみだく …

no image

MagicaVoxelとDMM.makeでオリジナルフィギュアを作ろう

もくじ1 読まなくても良い前書き2 概要3 MagicaVoxel3.1 フィギュアの自立の有無3.1.1 基本的に自立しません3.1.2 どうしても自立させたいなら3.2 折れる可能性を考慮する3. …

no image

DCEXPO2017に行ってきました

10/27~29にかけて、お台場の日本科学未来館で開催されたデジタルコンテンツエキスポ2017を見に行ってきました。 どれも見ごたえのある展示ばかりで、非常に面白かったのでいくつか紹介したいと思います …

no image

MagicaVoxelでUnity用の人間モデルを作ろう(東北ずん子配布もあるよ)

もくじ1 概要1.1 目標1.2 手順1.3 作成モデル2 MagicaVoxel2.1 パーツ分割2.2 出力3 Blender3.1 インポート3.2 モデルの初期調整3.2.1 重複する頂点の削 …

no image

GW自由研究 – なぜ日本の路面電車は廃れたのか

路面電車と言えば古き良き昭和の乗り物、というイメージですよね。 広島や函館など、一部ではまだ運行が続いている路線もあるものの、それらは「昭和の臭いが残っている」というような扱いです。 以前ブラタモリで …