No.7ベストアンサー
- 回答日時:
> というのは、最適化をせずに、明示的にインライン指定をしなくても自動でインライン展開(可能な限り)をしてくれるということですね。
> 逆にCでは最適化をするかインライン指定をしないとインライン展開(可能な限り)をしてくれないということですか?
ちょっと違います。
確かに、明示的にinlineを付けなくても、最適化でインライン展開されることはありますが、ここで取り上げているのはinlineというキーワードの意味についてです。
C++ではinlineを付けた関数はインライン展開を目指すのに対して、Cではinlineを付けた関数は高速呼び出し(実現方法は任意)を目指すというわけです。
> > プロセッサ依存の関数ベクタ
> よく分からないので勉強します
通常、関数を呼び出すには16~64ビット程度のアドレスを指定する必要があります。それを、関数ベクタ(関数のアドレスを集めたテーブル)に予め登録しておき、何番目の関数というように(ハード的に)指定すれば、もっと効率よく関数を呼び出せます。
他には、絶対アドレスではなく、相対アドレスで指定すれば、関数呼び出しを効率化できる可能性があります。
私自身プログラミングは上位アプリケーションしか作ったことがなく、インライン展開も「オプティマイザで出来ればインラインしとこう」くらいでした。
分からないキーワードがたくさん出てきたのでもっと勉強します。
とても参考になりました。ありがとうございました。
No.6
- 回答日時:
#3です。
私がアセンブラを組んでいたときは、OSがプロセスに割り当てたメモリの下位番地がスタックに割り当てられるので、特別スタックをプログラマが意識する必要はなかったように思います。今は変わっているんですかね。
ただ自動的に割り当てられたスタックには限りがありますので、再帰の階層が深くなりすぎると、スタックオーバーフローのエラーが出ますので、そのときは、プログラムをリンクする段階でスタック領域を確保できるようにたいていのコンパイラはなっていました。
No.5
- 回答日時:
末尾再帰の場合にはループに展開できる可能性があることは既に回答が出ている通りです。
他に、再帰関数の引数の一部が定数であれば、関数の定義次第ではインライン展開できる可能性があります。
もし、引数の全部が定数であれば、単なる右辺値になったり、関数内での副作用の部分だけが直接インライン展開される可能も、「原理的には」考えられます。
> C以外の言語でも、再帰関数のインライン展開が出来るプログラム言語があれば教えてください。
C++とか(多分期待している答えは違うんでしょうね)。
C言語もC99でinlineが標準でサポートされるようになりましたが、C++のinlineとは微妙に仕様がことなります。
C++では文字通り(可能な限り)インライン展開させるための機能ですが、C99では(可能であれば)通常より高速に呼び出す方法を採用させるための機能です。それはインライン展開でもよいですし、プロセッサ依存の関数ベクタを使ったり、ハード的な機能を利用したり、関数の定義によって方式を選択したりしても構わないわけです。
C言語とC++とではインライン展開の仕様が違うんですか。
> C++では文字通り(可能な限り)インライン展開させるための機能
というのは、最適化をせずに、明示的にインライン指定をしなくても自動でインライン展開(可能な限り)をしてくれるということですね。
逆にCでは最適化をするかインライン指定をしないとインライン展開(可能な限り)をしてくれないということですか?
> プロセッサ依存の関数ベクタ
よく分からないので勉強します
ありがとうございました。
No.4
- 回答日時:
普通はできないです。
引数の受け渡しによる値の保持をするスタックを自前で作ればいいのかもしれませんが、なにやってんだかわかんないですよね。
それに、もしインライン展開できるとしても、インライン指定した関数がコンパイラによってインライン展開されるかどうかはわかりません。
もともとできるかぎりインラインにしてねという指定だからです。
大抵の場合、再帰関数はループに置き換えできると思うので、初めからループとしてコーディングした方がいいと思います。
自前でスタックを作るのは訳が分からなくなりそうですね。関数コールのオーバーヘッドが気になるようなら素直にループ構造に置き換えたほうがいいですね。
No.3
- 回答日時:
長い間アセンブラでプログラムを組んでいないので、自信ありませんが、再帰関数の場合、スタックで引数のやり取りをするぐらいで、他の処理は普通の関数と同じだったと思います。
No.2
- 回答日時:
一般論として、再帰関数は次のような方法によるインライン展開が可能です。
(1) あらかじめ決めた数段分だけ展開する
例えば「f()がf()を呼ぶ」かわりに、f()のコピーを2つ作成しておき「f()がf2()を、f2()がf3()を、f3()がf3()を呼ぶ」ように展開します。(常にこのような展開が可能なわけではありません。)
すると、f()→f2()とf2()→f3()の各呼び出しは再帰ではない普通の関数呼出になるので、f()とf2()は通常の関数と同様のインライン展開が可能になります。
このような形にすることで、ループアンロールと同様のメリットがあります。
(2) 「終端再帰関数」を単純ループに置き換えて展開する
終端再帰関数とは、関数実行の最後で再帰呼出を行う再帰関数のことです。このような形の関数の場合、これを再帰ではなく単純ループの形に書き換えることが可能です。(常に可能なのか、あるいは正確にはどのようにして「終端再帰」を見分けるのか、という厳密な定義は知りません。)
ですので、再帰関数が終端再帰関数であれば、単純ループに置き換えた上で通常の関数と同様のインライン展開が可能になります。
(1)では階乗計算などで実現できそうですね。
(2)ではインラインで出来ない再帰構造は「終端再帰」に変えた方がいいということですね。(オーバーヘッド軽減のため)
「終端再帰」というのがよく分からないので勉強してみます。
ありがとうございました。
No.1
- 回答日時:
普通はできないです。
ただし、いわゆる末尾再帰は、ループに展開できます。
Lisp,Schemeなどの関数型言語では、ほぼ必須の機能です。
C++等では、実現している処理系と思いますが。
末尾再帰でないループは、スタックを自前で作ることでループに展開できますが、これを自動的にやってくれる最適化機能は、多分ないと思います。
> いわゆる末尾再帰は、ループに展開できます。
末尾再帰がよく分からないので勉強します。
末尾再帰に修正したい場合は自力で修正しないといけないんですね。
関数設計時に末尾再帰を頭に入れておかないといけないですね。
ありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・【大喜利】【投稿~11/12】 急に朝起こしてきた母親に言われた一言とは?
- ・好きな和訳タイトルを教えてください
- ・うちのカレーにはこれが入ってる!って食材ありますか?
- ・好きな「お肉」は?
- ・あなたは何にトキメキますか?
- ・おすすめのモーニング・朝食メニューを教えて!
- ・「覚え間違い」を教えてください!
- ・とっておきの手土産を教えて
- ・「平成」を感じるもの
- ・秘密基地、どこに作った?
- ・【お題】NEW演歌
- ・カンパ〜イ!←最初の1杯目、なに頼む?
- ・一回も披露したことのない豆知識
- ・これ何て呼びますか
- ・チョコミントアイス
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・これ何て呼びますか Part2
- ・許せない心理テスト
- ・この人頭いいなと思ったエピソード
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・あなたの習慣について教えてください!!
- ・ハマっている「お菓子」を教えて!
- ・高校三年生の合唱祭で何を歌いましたか?
- ・【大喜利】【投稿~11/1】 存在しそうで存在しないモノマネ芸人の名前を教えてください
- ・好きなおでんの具材ドラフト会議しましょう
- ・餃子を食べるとき、何をつけますか?
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・家の中でのこだわりスペースはどこですか?
- ・つい集めてしまうものはなんですか?
- ・自分のセンスや笑いの好みに影響を受けた作品を教えて
- ・【お題】引っかけ問題(締め切り10月27日(日)23時)
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・架空の映画のネタバレレビュー
- ・「お昼の放送」の思い出
- ・昨日見た夢を教えて下さい
- ・ちょっと先の未来クイズ第4問
- ・【大喜利】【投稿~10/21(月)】買ったばかりの自転車を分解してひと言
- ・メモのコツを教えてください!
- ・CDの保有枚数を教えてください
- ・ホテルを選ぶとき、これだけは譲れない条件TOP3は?
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・【コナン30周年】嘘でしょ!?と思った○○周年を教えて【ハルヒ20周年】
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
UWSCの終了の仕方
-
VBAで3秒だけ時間を止めたい
-
画面を強制的に再描画させる方法
-
C#で別のフォームのprogress ba...
-
流れ図(フローチャート)が分か...
-
乱数の桁数指定、または範囲指定。
-
Pro Tools の 波形を伸ばす方...
-
VB2010でCSVファイルの読み込み
-
アクティブセルから、A列最終行...
-
null 参照の例外が実行時に発生...
-
vb.netからエクセル関数書き込み
-
ネットワークループとルーティ...
-
【VBA】全て空白のセルの列の非...
-
エディットボックスのテキスト...
-
アセンブラによるウェイト(WAIT...
-
Application->Run();の機能につ...
-
JAVA グリッド
-
動的メモリ 解放がうまくいかない
-
VBA for i=1 to lastrow
-
EXCEL VBA ユーザーフォームの...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
UWSCの終了の仕方
-
画面を強制的に再描画させる方法
-
Escキーを押すと、中断する時と...
-
DOSコマンドのループ内のTIMEコ...
-
VBAでの一時停止と再開の方法
-
VBAで3秒だけ時間を止めたい
-
範囲指定したセルを1つずつ飛...
-
CSVファイルの特定の行だけを読...
-
vb.netからエクセル関数書き込み
-
ループフリー
-
GIFアニメをループさせたくない
-
VBA for i=1 to lastrow
-
DoEventsが必要な理由について
-
乱数の桁数指定、または範囲指定。
-
多重ループの抜けだし方
-
アクティブセルから、A列最終行...
-
Do whileでExitせず、ループの...
-
ボタンが押された時にループか...
-
データベースをEOFまでループさ...
-
テキストボックスの名前に変数...
おすすめ情報