No.2ベストアンサー
- 回答日時:
「(unsigned char)(++(f) -> fpi)[-1]」についてですね。
まず、演算子の優先順位は「(f) -> fpi」が一番最初です。
たぶん「今、読み出すべき文字を指しているポインタ」が「fpi」なのでしょう。
次の優先順位は「++」ですから、fpiを「++」、つまり、インクリメントします。
インクリメントによって「fpiを次に読み出すべき場所」に更新しています。
次の優先順位は、要素参照の「[-1]」ですから、そのポインタに対して「ポインタから-1の位置にある要素を参照」しています。
つまり「さっきインクリメントする前に指してた場所の要素」を取り出してる訳です。
まとめると「今fpiが指してる場所からデータを1つ取り出して、fpiを1つ進めている」のです。
ぶっちゃけ
((--((f)->blevel)>=0)?(unsigned char)(*(f)->fpi++) : _fgetc(f))
と同じですが、判りにくいマクロですね。
重要なのは「[-1]」です。これは「値としての-1」ではなく「1つ前の場所」を意味します。
例えば
unsigned char c;
unsigned char buf[] = { "ABCDEFGHI" };
unsigned char *p;
p = &buf[5]; // pは「F」を指す
c = ++p[-1];
とした場合。
c = ++p[-1];
は「pを1つ進めGを指すようにしてから、pが指す場所から-1した場所にあるデータであるFを取り出してcに入れる」です。
つまり
c = ++p[-1];
と
c = *p++;
は「同じこと」をします。
で、なんで「こんな回りくどい書き方をするか」ですが、理由は「1行の中で、getcを複数使った場合」を考えての事だろうと思われます。
たぶん「式の評価順序による想定外の副作用」を防ぐ理由で「ほげほげ++」の使用を避け「++ほげほげ」を使いたかったのだと想像します。
しかし「式の評価順序による想定外の副作用」は「++ほげほげ」も「ほげほげ++」も「どっちも一緒」なので、マクロ作者の期待する「副作用の予防」にはなっていませんね。
蛇足ですが、最後の「_fget」は「_fgetc」の書き写し間違いですよね?
この回答へのお礼
お礼日時:2009/01/24 07:08
回答ありがとうございます。特に[-1]」について例を上げ,説明して頂きまして大変参考になりました。ただ、私が勉強不足のため優先順位の詳細がわからないので別途質問したいと思います。
No.4
- 回答日時:
う~ん,
(++ほげ)[-1]
にしているのはもっと単純に
「++ほげ」の方が「ほげ++」より速いんじゃないかと思った
くらいだとおもうんだけど>#2.... この辺はアセンブリレベルまで落としてみないと見えない世界ですね.
「評価順序」って話をしたら, いずれにしても「2つの getc のうちどちらを先に評価するかわからない」時点でおしまい. ま, これはマクロバージョンでも関数バージョンでも同じことだけど.
No.3
- 回答日時:
蛇足ですが。
「((--((f) - > blevel)>=0)」は「fpiが指すバッファの残りのバイト数を表わすblevelを1つ減らし、減らした結果がマイナスかどうか?」を判定します。
まだある(減らした後で0以上になった。0を含む)なら、fpiを1つ進めて、fpiが指す場所にあるデータを取り出し、unsigned charにキャストして返します。
もう無かった(減らした後でマイナスになった)なら、直接データを取り出せないので_fgetc(f)を呼びます。
呼ばれた_fgetc()関数は、バッファが空になっているので、開かれたファイルからデータを読み込み、バッファに格納します。
そして、fpiをバッファの先頭に再設定し、blevelも「バッファの残りバイト数」に再設定します。
最後に、バッファの先頭にあるデータを取り出し、fpiとblevelを1つ分更新し、取り出したデータを返り値にしてリターンします。
なお、バッファが空になっている時にファイルからデータを読もうとして「ファイルが尽きた」と判った場合は、ストリームに「EOFになった」とマークを付けた上で、EOFを返します。
ここまでが、呼ばれた_fgetc()関数の動作です。
>フアイルの終わりである場合のマクロの動作を教えていだきたい
そう言った訳で「ファイルが終わりになるのは、マクロの中ではなく、_fgetc()の中で起きる」のです。
マクロで「まだバッファにデータがある」と判断している間は_fgetc()は呼ばれないので「ファイルが終わりになる事はありえない」のです。
そして、ファイルが終わりになった場合は、blevelを幾らデクリメントしてもblevelはマイナスのままなので、常に_fgetc()が呼ばれます。そしてEOFは_fgetc()が返して来ます。
注意して欲しいのは「マクロ中にある[-1]はEOFではない」と言う事。
蛇足の蛇足ですが「_fgetc()が、EOF状態の時にblevelを固定しないで放置している」と言う場合、EOFになったストリームに対しマクロのgetcを使い続けると「blevelが1づつ引かれ続け、ある時、アンダーフローして0に戻り、呼ばれる筈の_fgetc()が呼ばれない」ので、非常に低い確率で誤動作します。
ま、普通、getcでEOFが返って来たら「ファイルを閉じて、それ以上getcしない」ので、問題は起きない筈なんですけどね。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
- ・ゆるやかでぃべーと タイムマシンを破壊すべきか。
- ・歩いた自慢大会
- ・許せない心理テスト
- ・字面がカッコいい英単語
- ・これ何て呼びますか Part2
- ・人生で一番思い出に残ってる靴
- ・ゆるやかでぃべーと すべての高校生はアルバイトをするべきだ。
- ・初めて自分の家と他人の家が違う、と意識した時
- ・単二電池
- ・チョコミントアイス
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
メッセージボックスのOKボタ...
-
エクセルで特定の列が0表示の場...
-
Excel・Word リサーチ機能を無...
-
特定のPCだけ動作しないVBAマク...
-
一つのTeratermのマクロで複数...
-
【EXCEL VBA】オートシェイプを...
-
Excel マクロ VBA プロシー...
-
wordを起動した際に特定のペー...
-
Excel マクロでShearePoint先の...
-
ExcelのVBA。public変数の値が...
-
Excel VBAからAccessマクロを実...
-
エクセルに張り付けた写真のフ...
-
特定文字のある行の前に空白行...
-
ExcelVBAでPDFを閉じるソース
-
マクロで待機時間を作りたい
-
VC++ 2008 EXPRESS "_T"識別子...
-
EXCELマクロでのThisisWor...
-
Wordのマクロでクリップボード...
-
VBA アドインについて お詳しい...
-
エクセルマクロでワードの一ペ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Excel・Word リサーチ機能を無...
-
特定のPCだけ動作しないVBAマク...
-
エクセルで特定の列が0表示の場...
-
Excel マクロ VBA プロシー...
-
メッセージボックスのOKボタ...
-
一つのTeratermのマクロで複数...
-
ExcelのVBA。public変数の値が...
-
エクセルに張り付けた写真のフ...
-
Excel VBAからAccessマクロを実...
-
TERA TERMを隠す方法
-
Excel マクロでShearePoint先の...
-
ExcelVBAでPDFを閉じるソース
-
特定文字のある行の前に空白行...
-
マクロ実行時、ユーザーフォー...
-
wordを起動した際に特定のペー...
-
エクセルで別のセルにあるふり...
-
ソース内の行末に\\
-
マクロで空白セルを詰めて別シ...
-
【EXCEL VBA】オートシェイプを...
-
エクセルのマクロをセルの値に...
おすすめ情報