« 2006年09月 | メイン | 2006年11月 »
2006年10月22日
C言語:static 変数
#include
void counter( );
void main() {
int i;
for (i=0; i < 10; i++) {
counter();
}
}
void counter( ) {
int cnt=0;
cnt++;
printf("%d回目の呼び出しですn", cnt);
}
実行してみてください。どうなりましたか?
実は、変数には、人間で言うところの寿命に相当するものがあるのです。
通常の変数は、宣言した場所のすぐ外側にある、「{ 」と「 }」の間までが寿命になっています(この範囲を、その変数のスコープと言います)。
上の例ならば、
void counter( )
{ ←ここから
int cnt=0;
cnt++;
printf("cntは今、%dですn", cnt);
} ←ここまで
ということは、一旦、関数 counter から main 関数に戻った時点で、変数 cnt の寿命は尽きてしまっていたのです。それ以降、関数 counter に入るたびに、変数cntは作られて、またすぐに寿命が尽きているのです。
これでは、困ってしまいますね。正しくカウントアップできません。
これは、次のように変数を宣言すると、うまく行きます。
int counter( ) {
static int cnt;
cnt++;
printf("cntは今、%dですn", cnt);
}
どうなりましたか?
staticを付けると、変数は、プログラムの開始から終了まで生き続けます。つまり、プログラム中ずっと有効な寿命を与えられたのです。
さっそくコンパイルして、実行してみてください。
ちなみに、staticを付けると、変数は自動的に0に初期化されます。しかし、便利だと思っても、多用しないでください。あなたのプログラムを見た人は、staticを付けた変数には、何か特別な意味があるはずだと解釈するからです。
しかし、static変数も結局は、関数 counter の中でしか使えません。
http://www.sgnet.co.jp/c/10-2.htm
C言語:static 関数への使用
static宣言された関数は静的関数と呼ばれ、関数外静的変数と同じように関数の有効範囲が定義されているファイル内のみ有効で、定義されているファイル外では利用できなくなります。
これは、オブジェクト指向のカプセル化(情報隠蔽)に似ています。
一口メモ
カプセル化というのは、誰でも利用できる関数や変数は極力少なくする事を言います。
これは、他の人(外部のファイル)は絶対に呼び出してはいけない、もしくは呼び出す必要が無いような関数は外部から見えなくしてしまった方が誤使用が減り、安全性が高くなるとい考えに基づいています。
静的変数を作る方法はいたって簡単で、プロトタイプ宣言の頭と関数定義の頭に static と書くだけです。注意点としては、静的関数のプロトタイプ宣言をヘッダファイルに書いてはいけません。これは静的関数の性質を考えれば当然の事ですが、一応頭に入れておいてください。
/* 静的関数の関数プロトタイプ宣言の例 */
static int testfunction( int value );
/* 静的関数の関数定義の例 */
static int testfunction( int value )
{
int a;
:
:
:
return a;
}
http://www.paw.hi-ho.ne.jp/takadayouhei/technic/39.html
C言語:extern
C言語:extern
「MW web studio(http://homepage1.nifty.com/aok2/)」
全ファイル中のどこかに定義してある、という意味です。複数ファイル構成で分割コンパイルする場合に必要で、一般的には共通ヘッダファイルに記述します。
ファイル1個プログラムではあまり使い道がありません。しかし、厳密にはファイル1個でもライブラリ内の関数や変数を参照する場合にextern宣言が必要です。ライブラリはコンパイル済みCファイル(の集合体)と考えるためです。
2つの使い方があります。
1. 関数(のプロトタイプ宣言)
2. グローバル変数(他ファイル内に定義されている)
1. 関数のプロトタイプ宣言
関数のプロトタイプ宣言にexternを付ける付けないは、あまり問題になりません。
----------- a.c -----------
int func_A( int n ); /* OK */
extern int func_A( int n ); /* OK */
int func_A( int n )
{
}
----------- b.c -----------
int func_A( int n ); /* OK */
extern int func_A( int n ); /* OK */
int func_C( int n )
{
/* a.c の func_A を呼んでいる */
func_A( n );
}
extern は、「全ファイル中のどれかに定義されている」ですから、 extern int func_A(int n); は、a.c でも、b.c でも同じように宣言できます。
staticではない関数は、自動的に外部から見えると解釈されます。なので関数の場合は、extern を省略できます。省略しないほうがいいですが。
戻り値が int型の関数は、プロトタイプ宣言すら省略できますが、なるべくプロトタイプ宣言をしましょう。
2. 変数
2.1 正しい使い方
まずは正しい使い方です。 a.c 内で定義された int a; を b.c 内で使っています。
----------- a.c -----------
int a;
func_A()
{
a = 1;
}
----------- b.c -----------
extern int a;
func_B()
{
a = 2;
}
2.2 コンパイルエラー
この例では、a = 2; の a は、b.c内では定義されていないよ!とコンパイルエラーになります。
----------- b.c -----------
/* extern int a; */
func_B()
{
a = 2;
}
2.3 リンクエラー(1)
----------- b.c -----------
/*extern*/ int a;
func_B()
{
a = 2;
}
コンパイルはOKです。しかしリンクで、変数 a が、a.c、b.c 2箇所で定義されています?とリンクエラーになります。
一つのプログラム内では、同じ名前のグローバル変数は使えません。(グローバル変数とは、関数の外で定義した変数)
似たような例を紹介しますが、一つの関数内では、同じ名前のローカル変数は使えません。(ローカル変数とは、関数の中で定義した変数)
func_A()
{
int x;
int x; /* エラー */
}
2.4 リンクエラー(2)
----------- a.c -----------
/* int a; を定義しない */
----------- b.c -----------
extern int a; /* どこかにあるはず */
func_B()
{
a = 2;
}
b.c のコンパイルはOKです。b.c の変数a の扱いは「別ファイルにあるはず」と、変数a に関する問題を先送りにします。しかしリンクのとき、全ファイルを見渡しても変数a はどこにもない、とリンクエラーになります。
「MW web studio(http://homepage1.nifty.com/aok2/)」
2006年10月03日
HDD ハードディスク ドライブ セクター 不良
/var/log/message等に
「kernel: hda: dma_intr: status=0x51」とかが残っているのを見つけたら、ハードディスク障害が発生している可能性が高いです。
badblocks -vs -o hda1.sector /dev/hda1
とやると 不良セクタがあった場合、「hda1.sector」ファイルができます。(不良セクタの場所なんかが記録されます。)
fsck -l hda1.sector /dev/hda1
とやるとその不良セクタを使用しないようになります。