変数の宣言効率と有効範囲について。

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

変数の宣言効率と有効範囲について。

#1

投稿記事 by Kou » 16年前

お世話になってます。以前質問させて頂いた、Kouです。
今回C言語の変数についていくつか質問させて頂きます。(初歩的で申し訳ありません・・・)

以下長文になりますが。
1.変数宣言位置の効率について。
    ・ゲームに限らずプログラム内では多くの変数を使用しますが、
   いろいろな関数で使用する変数(敵データの構造体配列、弾データの構造体配列など)を宣言するのに、
   グローバル変数として宣言するのと、staticで静的ローカル変数として宣言するのと、
   どちらがメモリ効率が良いのでしょうか?

   簡単に考えると、前者なら変数の関数間受け渡しを考えなくても良いし、
   後者ならオブジェクト化とまでは行かなくても、ある程度処理を分けれるので、
   保守的な面でメリットがあるかなと・・・

   どちらで宣言してもメモリ効率の違いが無いのであれば、後は個人の好みの問題ですが、
   違いがあるのであればと思いまして・・・。

2.変数の有効範囲について。
  ・自作関数内で構造体データをmallocで確保した場合、そのメモリ領域を示すポインタ変数は、
   関数から出た時点で破棄される訳ですが、確保したメモリ領域はfreeで開放するまで残っていますよね?
   仮に

   struct DATA_t{
          int x;
          int y;
      };

      void init( void );

      int main(){
          init();

          return 0;
      }

      void init( void ){
           struct DATA_t *p;

           p = ( struct DATA_t* )malloc( 10 * sizeof( struct DATA_t ) );
      }

   上記の場合init関数内のポインタ変数pは、関数を出た時点で破棄されるので、確保された領域の
   アドレスが迷子になります。(迷子になるんだと思っています・・・)
   これは、

   struct DATA_t{
          int x;
          int y;
      };

      struct DATA_t* init( void );

      int main(){
          struct DATA_t *p;
          p = init();

     実際の処理・・・・

          free( p );

          return 0;
      }

      struct DATA_t* init( void ){
           struct DATA_t *p;

           p = ( struct DATA_t* )malloc( 10 * sizeof( struct DATA_t ) );

           return p;
      }

   こうすれば関数内で確保したメモリ領域を他の関数でも使用できるのでしょうか?

C言語(File拡張子は.cppです)
VS C++ 2008EE
です。

初歩的な質問で申し訳ありませんが、回答よろしくお願いします。

sizuma

Re:変数の宣言効率と有効範囲について。

#2

投稿記事 by sizuma » 16年前

Kouさんこんにちは

僕の意見は参考程度にお願いします。
Cでゲーム作ったことない人ですし。

1メモリ効率

グローバル変数、ファイル内のstatic変数、static指定したローカル変数はスコープの違いだと記憶してます。
なので普通に考えるとメモリ効率は同じだと。
どれもプログラム開始から終了までメモリを占拠してますんで。
個人的にstaticはキライです。あくまで好みですが・・。


2malloc

mallocで確保したメモリはfreeされるまで開放されないです。
っていうかfreeされても
「ここ上書きしていいよー」ってflagをオンにして、前後が使われてない領域であれば一まとめにする
ってデフラグみたいな仕事をするので、おそらくfreeしても上書きするまでは使えると思いますよ。
mallocで確保したメモリはfreeするまで確保されたままなんで、関数内で開放しないとメモリリークの恐れもあると思うので気をつけないとですね。
JavaとかC#だとガーベジコレクション勝手にしてくれるんで、気にしなくてもいいんですけど

たかぎ

Re:変数の宣言効率と有効範囲について。

#3

投稿記事 by たかぎ » 16年前

> C言語(File拡張子は.cppです)

拡張子が.cppということはC++ですね。
以下、そのつもりで回答します。

> 1.変数宣言位置の効率について。

メモリ効率だけでいえば、関数内でstaticを付けて宣言したオブジェクトが最もメモリを消費します。

> 2.変数の有効範囲について。

書かれている認識であっています。
ただし、

> 確保したメモリ領域はfreeで開放するまで残っていますよね?

freeで「解放」するまでですよね。
freeにはメモリを「開放」する機能はありません。
http://www.kijineko.co.jp/tech/supersti ... -free.html

メモリ管理の手間を省きたければ、std::tr1::shared_ptrやstd::vectorを使うなどするとよいでしょう。

sizuma

Re:変数の宣言効率と有効範囲について。

#4

投稿記事 by sizuma » 16年前

>開放、解放
確かに意味が変わりますね。気をつけます。

Kou

Re:変数の宣言効率と有効範囲について。

#5

投稿記事 by Kou » 16年前

sizumaさん、たかぎさん回答ありがとうございます。

>たかぎさん
 紛らわしい記述ですみません。拡張子.cppにしてあるのは、コード記述の便宜上.cppの方が良かったからで、
使用言語自体はC++ではなくC言語です。

 それと、freeに関する記述読ませて頂きました。
確かに開放ではな解放ですね・・・
ご指摘ありがとうございます。

 たかぎさんの回答でstaticが一番効率が悪いとありましたが、よくC++の解説書で
「何でもグローバル変数にしないで、クラスを使用する。」とあります。
これはC言語には当てはまらないのでしょうか?

 たしかにC言語にはクラスはありませんが、処理のパック化と言うか、関数内での処理完結化はできますよね?
例えば今作っているSTGで使用した自機のデータ構造(構造体定義)や移動処理、弾の発射処理などを別ファイルにしておき、次に別のSTGを作る時にそのファイル(前回作成した関数や構造体)に手を加えずに利用する・・・
ようはライブラリと同じような使い方を.cppや.hの状態でする場合、どのような構造(変数の宣言方法など)
が一番良いのでしょうか?

たかぎ

Re:変数の宣言効率と有効範囲について。

#6

投稿記事 by たかぎ » 16年前

>  たかぎさんの回答でstaticが一番効率が悪いとありましたが、よくC++の解説書で
> 「何でもグローバル変数にしないで、クラスを使用する。」とあります。
> これはC言語には当てはまらないのでしょうか?

必要に応じて使い分けるべきです。
メモリを1バイトでも節約したい状況でなければ(Windowsではないと思いますが)、static付きの局所オブジェクトを使うことによるメモリ効率の低下は気にすることはありません。
なぜ、static付きの局所オブジェクトのメモリ効率が悪くなるかも説明しておきます。
int foo()
{
  static int x = bar();
  return x++; 
}
のような関数があった場合、最初にfooが呼び出されたときだけbarが呼び出されることになります。
これを実現するには、内部的には
int foo()
{
  static bool __f = false;
  static int x;
  if (!__f)
  {
    x = bar();
    __f = true;  // ← この行、追加しました。
  }
  return x++;
}
のようなコードをコンパイラが生成することになります。
この暗黙的に挿入されるコードの分だけメモリ効率(実効効率も)が悪くなります。

Kou

Re:変数の宣言効率と有効範囲について。

#7

投稿記事 by Kou » 16年前

詳しい解説付での回答ありがとうございます。

staticにすると、余計なコードが増える事によりステップ数(暗黙の変数?も)が増え、結果メモリ使用量と
実行効率が悪くなるんですね。

sizumaさんとたかぎさんの回答と拝見して、現在のマシンスペック(一般的に)では変数宣言によるメモリの
使用量(効率)は気にしなくても良いようですが、やはりstaticにした際のステップ数増加は、乱用すると無視
出来ないものになりそうですね。特にSTGのような処理速度を出来るだけ上げたい物の場合は・・・

グローバル変数が嫌いとかじゃないんですが、何とか関数内で完結出来ないかと考えたんです。
その部分を考える事で、少しはレベルアップできるかな?・・・なんて思ってしまいました。

とりあえず状況による使い分けを実践して色々な組み方を勉強したいと思います。
sizumaさん、たかぎさん、ありがとうございました。

閉鎖

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