1.構造体のじょーずな使い方
ファイルや関数をまたいだ構造体の使い方について書いてみます。
何故構造体なのかというと、大きなデータを簡単に受け渡しできるため、ロボットのプログラミングには非常に便利だからです。
複数のファイルから使う変数を値ではなく参照で共有することにより、プログラムが軽くなっていることに注目してください。
(まあ、実はコンパイラの設定によっては、自動的にグローバル変数を参照渡ししてくれたりするらしいんですけど・・・。なんか気持ち悪いから。これについては「SuperHファミリのCプログラミング」などの本を読まれるといいと思います。たしか。)
早速以下にサンプルを示しながら説明します(そんな大層なものでもないけど)
any_define.h, main.c, function.c の三つのファイルがあるとして見てください。
//any_define.h
struct TEST
{
unsigned int test1;
unsigned char test2[4];
unsigned int *test3;
};
ヘッダファイルで構造体を定義しておきます。
ここでは実体は生成してません。
//main.c
#include "any_define.h"
void main(void)
{
struct TEST test; //ここで(メイン関数内で)生成する
test.test1=10; //初期値を与える(他のメンバにも適宜行う)
function(&test); //サブルーチンへは構造体testのアドレス(先頭アドレス)を渡す
}
メイン関数内で構造体の実体を生成しています。
サブルーチンへはアドレスを渡していることに注目してください。
test.test1に初期値を与えているのは、function1内で構造体のメンバを使うときに値が不定にならないようにするためです。なぜtest1だけなのかと言うとほかのメンバを例として使うのが面倒だったから(笑)。test2もtest3も使うなら初期化すべきです。
//function.c
#include "any_define.h"
void function1(struct TEST *test)
{
int a;
a=test->test1; //まあ
printf("test1は%dだったよ\n",a ); //こんな感じに使えばーという例ですな
function2(test); //&testでないことに注目
}
void function2(struct TEST *test)
{
int b;
b=test->test1;
printf("やっぱりtest1は%dだったよ\n",b );
}
同じ構造体のポインタを仮引数に持つ二つの関数function1とfunction2が登場しています。
基本的に二つの関数の構造は同じですね。
構造体のポインタのメンバの値は「アロー演算子」->を使います。
test->test1は(*test).test1と同じことというわけです。
さて、function1はポインタが仮引数なのでmain関数において「&」を使ってアドレスを渡されていたんですが、function2はどうでしょう。
function1のなかでは・・・あれ?「&」が無い。
まあ、そりゃそうですよねfunction1の仮引数として渡されたtestはもうすでにアドレスなんですもん。要約すると、構造体ポインタを仮引数とする関数から他の関数にその構造体を渡すときには「&」は要らないぞーということです。
以上述べたように、渡して~渡して~で変数を共有できています。
どこで実体を生成するか(mainですればいい)とか、どこで初期化するか(mainで(以下略))とか、externをどこにつけるか(つけなくて良い)を気にしなくていい方法です。
あくまでもメインが中心でそこから他の関数に変数を分け与えていくようなこの方法は筋が通っていて僕は気に入ったんですが、皆さんはどうでしょう?
C言語初心者向けに、参考になったら幸いです。
(2010/3/14)
あ、でも割り込みの処理なんかにこの方法で変数を使うのは難しいですね・・・。いや、書いてから気づきましたが。率直に構造体をグローバルにしておいた方がいいかもですね・・・。