龍神録プログラムの第5章について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
竜安吉

龍神録プログラムの第5章について

#1

投稿記事 by 竜安吉 » 14年前

C++学び始めでゲーム製作をしようとしている者です。
龍神録プログラムの第5章について質問します。
extern宣言の分岐による処理の部分ですが、過去ログなども読んだ上で私の理解が正しいかどうかご教示ください。

コード:

--GV.h内--

#ifdef GLOBAL_INSTANCE
#define GLOBAL
#else
#define GLOBAL extern
#endif

#include "function.h"		//関数宣言

//画像用変数宣言部
GLOBAL int img_ch[2][12];       //キャラクタ画像9枚分 X2(変身用)

//構造体変数宣言部
GLOBAL ch_t ch;                 //キャラクタデータ宣言



--function.h内--

//graph.cpp
        //描画メイン
        GLOBAL void graph_main();

//key.cpp
        //現在のキー入力処理を行う
        GLOBAL int GetHitKeyStateAll_2();
        //受け取ったキー番号の現在の入力状態を返す
        GLOBAL int CheckStateKey(unsigned char Handle);

//laod.cpp
        //データのロード
        GLOBAL void load();
上記の部分で、main.cppからの呼び出しの際、変数はこの条件分岐でexternなしの定義がされることは理解できました。
しかしfunction.h内の関数については、main.cppではextern宣言しないといけないはずですが、変数と同じようにexternなしの宣言がされてしまうように思います。

これについて以下のような理解で正しいでしょうか。
①main.cppからの呼び出しによるexternなしの宣言は、プロトタイプ宣言である。
②extern宣言については、graph.cppやload.cppなどの別ファイルからの呼び出しでされるているからOK。


動作自体は問題ないのですが、いまいち自分で理解している気になりません。
よろしければご教示願います。よろしくお願いします。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 龍神録プログラムの第5章について

#2

投稿記事 by softya(ソフト屋) » 14年前

#includeや#ifdefはプリプロセッサの命令ですのでコンパイル時に動作は確定します。
なので、あまり呼び出すという表現は使いません。

C言語の規格上、関数のプロトタイプ宣言のexternですが実は無くても問題有りません。
なので、実際にはmainインクルードしているfunction.hでexternが付いてないのは間違いだと思うのですがたまたま上手く動いているって所だと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

竜安吉

Re: 龍神録プログラムの第5章について

#3

投稿記事 by 竜安吉 » 14年前

返答ありがとうございます。
main.cppからのインクルードでexternがつかなくても規格上動いてしまうが、本来はexternがついているのが正しいということでしょうか?

だとしたら関数については(main.cpp,graph.cpp,load.cpp...etc)→GV.h→function.hという流れではなく、
それぞれの頭に

コード:

#include "../include/GV.h"
#include "../include/function.h"
と記述して、function.hは

コード:

//graph.cpp
        //描画メイン
        extern void graph_main();
 
//key.cpp
        //現在のキー入力処理を行う
        extern int GetHitKeyStateAll_2();
        //受け取ったキー番号の現在の入力状態を返す
        extern int CheckStateKey(unsigned char Handle);
 
//laod.cpp
        //データのロード
        extern void load(); 
とするのがいいということでしょうか?
ちなみに上記のようにしても動作はしました。

迅速な返答ありがとうございました。よければまたご教示願います。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 龍神録プログラムの第5章について

#4

投稿記事 by softya(ソフト屋) » 14年前

規格上はexternが無くても良いので書かなくて良いのですが、externが書いてある場合と書いてない場合がある統一性の無さが問題ですね。
作者であるDixq(管理人)さんのミスだと思います。

ヘッダの関数のプロタイプ宣言は全部externを書いておいて問題ないので、GLOBAL の代わりにexternを書くかGLOBALとextern両方を止めてしまうか統一をお勧めします。
ヘッダのインクルード場所は変えなくて良いと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

竜安吉

Re: 龍神録プログラムの第5章について

#5

投稿記事 by 竜安吉 » 14年前

関数については変数とは違い、GLOBALを使った分岐は必要ないものと考え、以下のようにコードを変えました。

コード:

--GV.h内--

#include "function.h"       //関数宣言を分岐の前に持ってくる

#ifdef GLOBAL_INSTANCE
#define GLOBAL
#else
#define GLOBAL extern
#endif
 
//画像用変数宣言部
GLOBAL int img_ch[2][12];       //キャラクタ画像9枚分 X2(変身用)
 
//構造体変数宣言部
GLOBAL ch_t ch;                 //キャラクタデータ宣言
 
 
 
--function.h内--GLOBAL削除
 
//graph.cpp
        //描画メイン
        void graph_main();
 
//key.cpp
        //現在のキー入力処理を行う
        GLOBAL int GetHitKeyStateAll_2();
        //受け取ったキー番号の現在の入力状態を返す
        int CheckStateKey(unsigned char Handle);
 
//laod.cpp
        //データのロード
        void load(); 
以上で動作しました。
わかりやすい説明、ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る