C言語でint main(int argc, char *argv[])とメイン関数を宣言します。
2番目の引数はC言語の文法的にいうと文字列へのポインタの配列だとおもいますが、一般的な関数でこの引数に値を渡すとすると、以下のように宣言されたポインタ配列を渡すことになるとおもいます。
・宣言
char *pa[];
・関数への渡し
func(pa);
話が元に戻りますが、main関数でもらう場合は、プログラム外部から与えられた引数は(正確に言うとアドレス)、メモリ上ではC言語で書かれたexeファイルの外から実行時にプログラムファイルのメモリ上にコピーされるのでしょうか?
自分でもうまく表現できないのですが、
・コマンドプロンプトで引数を与えて実行
↓
・プログラムファイルのメモリ上に引数がロードされる
ということでいいんでしょうか?
自分でもなんだかうまく表現できないので、お暇な方でよろしいので、気が向いた人、回答ください。
よろしくお願いします。
No.3ベストアンサー
- 回答日時:
★ちょっと昔話。
・Windows より前の OS MS-DOS では、プログラムが実行されるとメモリ上に存在する
EXE ヘッダにコマンドラインの文字列と文字数が格納されます。
そして、C 言語で作成されたプログラムは main() 関数を実行する前にスタートアップ
ルーチンという処理が行われます。この処理の中に EXE ヘッダに存在するコマンドライン
文字列のコピーを作ります。その後、スペースで区切られた引数を char *argv[] に
セットしてから main() 関数が呼び出されます。
・よって、まとめると
(1)コマンドラインから実行
(2)プログラムをメモリ上にロード(EXE ヘッダに引数文字列がセットされる)
(3)スタートアップ処理で EXE ヘッダから C 言語のグローバル変数領域に引数文字列をコピー
(4)コピーされた引数文字列をスペース文字で区切って char *argv[] 配列にセット
(5)main() 関数に char *argv[] と区切った引数の個数を argc で渡す
↑
簡単に説明するとこんな感じになります。
・引数文字列はコピーしたものを *argv[] で使うため EXE ヘッダにある引数文字列は
書き換わりません。→正しくは EXE ヘッダにある引数文字列は書き換えてはいけない。
・上記のは MS-DOS という OS の話です。でも Windows のプログラムも同様な処理を行っている
と思います。EXE ヘッダ(PE情報)があるので。MS-DOS 時代よりも PE ヘッダが複雑でサイズが
増えていますね。この PE 情報の資料がほとんど見つかりませんね。英語サイトならありますが…。
最後に:
>・プログラムファイルのメモリ上に引数がロードされる
↑
プログラムファイルのメモリ上(EXEヘッダ)に引数文字列がロードされる
その後、プログラムのグローバル変数領域に引数文字列がコピーされる
そして、コピーされた引数文字列をスペース文字で分割される
そしたら main() 関数の char *argv[] として引数文字列が渡される
という順になります。
・ちなみに Windows API 関数に引数文字列を取得する GetCommandLine() があります。
これは多分、EXE ヘッダの引数文字列から直接ポインタで取得しているような気がします。
理由は、この関数で取得した引数文字列は書き換えないようにという注意書きがあるので。
でも、本当のところはよく分かりませんが…。注意書きを信じてコピーしてから使いましょう。
・他の OS については詳しく知りませんので 昔の MS-DOS、そして Windows 系で回答してみました。
・以上。
参考URL:http://wisdom.sakura.ne.jp/system/winapi/win32/w …
どうも、大変ご丁寧な解説ありがとうございます。
自分は、一応プログラム暦(アマグラム暦?)6年になります。コンピュータの内部動作とかまでようやくりかいできるようになり、今回、このような質問をした次第です。
その上でOh-Orange様のご回答は非常に参考になりました。WindowsでもUNIXでもいいのですが、とにかく内部的な動作がしりたかったのです。それで、Windows自体のCプログラムの呼び出し具合を書いていただいたので、この上ない、私自身のありがたい知識となりました。
MS-DOS時代からの方でいらっしゃるんですね。私はほとんどWinXPですので、昔の技術も興味あります。UNIXとか必死で勉強しています。
今回は大変ご丁寧な回答誠にありがとうございました。非常に勉強になりました。感謝しきれないくらいです。ありがとうございました。
No.5
- 回答日時:
ホスト処理系では、最初にmainが呼び出された後のことしか、規格上は扱われていません。
つまり、それ以前のことは処理系が勝手に決めることですので、一般論で語っても意味ありません。ちなみに、先ほど「最初に」と書いたのは、mainを再帰的に呼び出すことも可能だからです。その場合は、アプリケーション側でどんな風にメモリを割り付けるかによります。
どうもありがとうございます。
処理系によるんですね。今回は色々なかたのお話をお伺いし、OSがどの辺までCプログラムなどを扱うのかがなんとなく分かった気がします。今までは、OSとアプリケーションの境界線が漠然としていたために、少し疑問におもっていました。
しかし、皆さん、お詳しいですね。どこで、勉強するんですかね・・私自身書店などで結構立ち読みするのですが、全然、その辺の知識が身に付きません・・
今回は勉強になりました。本当にありがとうございました。
No.4
- 回答日時:
#2さんの通り、たいていプログラムの起動時に _CRTStartup() とかいった名前の関数が呼ばれて、そこで、コマンドライン引数などの解析(argc,argvへの格納)をして、main()を呼び出すって感じの処理をすしてます。
例えば、いにしえのDOSの時代には、
アドレス 80h にコマンドライン引数が格納されていました。
http://www5c.biglobe.ne.jp/~ecb/assembler2/1_1.h …
どうもありがとうございました。
#2様のおっしゃるとおりなんですね。私は、諸事情で大学すら行っていないので、深い知識は全然分からないので、ここの皆さんの知識には驚かされるばかりです。参考URLも見させていただきましたが、どこでそういったものは、見つけてくるのですかね・・
なにしろ、困ったらここで聞くしかないので。。
どうもありがとうございました。MS-DOSの頃のような基本的なことから勉強したいです。でも、その環境作りも今じゃ難しいですよね。なんとか、しがみついて、勉強していこうとおもいます。
目標は80歳で名を挙げることです・・
No.2
- 回答日時:
C言語の規格では、mainエントリ関数に渡されたコマンドライン文字列は書き換え可能ということになっています。
#元の文字列の長さを超えて書き込むとどうなるかは分かりません。
ということから、mainに来る前にメモリが確保されて文字列がコピーされている、と考えることができるのではないでしょうか。
どうもありがとうございます。
isle様の教えていただいたことから推測すると、確かに、mainに来る前に文字列がコピーされていると考えることが、確かなようですね。
C言語の知識は、つけようと思えば、いくらでも本に載っていますが、その辺のOSとのやりとりというか、OS内部部分まで関わってくると、なかなか、知識の身につけようがないですね。まして、昨今のパソコンOSは、非常に高度みたいですし。。なにか、MS-DOS時代がうらやましくなりもします。
ご回答ありがとうございました。参考になりました。
No.1
- 回答日時:
実は、厳密に言えば、C/C++のプログラムで最初に実行されるのは、main() ではありません。
引数の処理や、グローバル変数の初期化など、前処理をするプログラムがあります。
このプログラムが動いて、準備がすべて整った後で、main() という関数がこのプログラムから呼び出されます。
コマンドラインの引数をどのようにして渡すかは、コマンドプロンプトやOSの取り決めになります。その取り決めを理解して、main() がわかるようにセットアップするプログラムが、一番最初に動くということになります。
そういう小さな(小さくないかも)プログラムが、各コンパイラの各OS用に準備されています。これは、ユーザーには見えないうちに処理されてしまいます。
いわゆる「組み込み」の世界で、OSなど無いという段階では、main() を呼ぶまでのスタートアップルーチンも、はっきり見えますが。
どうもありがとうございます。
考えてみれば、実行ファイルというのは、機械語のレベルですもんね。C言語の文法で考えることがおかしいですね。
AsanoNagiさんが教えてくれたことは、理解できました。たかだかプログラム言語を扱ったところで、コンピュータ全体の動きにかかわることを考えようとしたのは、あさはかだったですね。
ん~。実に難しいですね。掘っても掘っても見つからない温泉のように、なかなか、コンピュータの底まではたどり着けませんね。組み込みをやればわかるということなので、いずれやったとき?は覚えておきます。
ご回答ありがとうございました。大変参考になりました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
「ヒープサイズの設定」て何?
-
VBAの配列サイズとメモリに関して
-
C言語で、メモリを解放しないで...
-
VB.netでUSBメモリの固有I...
-
mmap()
-
バッチファイルでの実行EXEのメ...
-
「memcpy」と「strcpy」について
-
C,C++プログラムの強制終了時の...
-
CPUやメモリの使用率を調べ...
-
エクセル キャッシュメモリー...
-
エクセルVBA 大容量CSVファイル...
-
エクセルのメモリ使用状況/Appl...
-
ウインドウズのシステムにおけ...
-
PIC 文字 を 数値に 変換
-
ファイルマッピング関数で失敗
-
値のコピーについて
-
動的確保できるメモリ容量
-
Macターミナルで実行中のプログ...
-
3のつく数字と3の倍数のみを表...
-
VBSの処理中一旦処理を止めて再...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBAの配列サイズとメモリに関して
-
C言語で、メモリを解放しないで...
-
C言語における再帰呼び出しの...
-
メモリ不足
-
「ヒープサイズの設定」て何?
-
動的メモリとexit(C言語)
-
エクセルのメモリ使用状況/Appl...
-
大容量のメモリ確保をスワップ...
-
【C言語】再帰が時間がかかる...
-
バッチファイルでの実行EXEのメ...
-
メモリのセグメント違反の解決...
-
「memcpy」と「strcpy」について
-
ExcelのVBAでメモリ解放できない
-
これて逆じゃないですか?
-
メモリを解放しないとどうなる?
-
ファイルマッピング関数で失敗
-
エクセルVBA 大容量CSVファイル...
-
メモリアロケーション異常の発...
-
エクセル キャッシュメモリー...
-
Apacheでバーチャルホストの最...
おすすめ情報