static関数
Copyright(C) 14May2003 coskx
複数のファイルからなる大規模プログラミングでは,一連の関数群を1つのファイルに作りこみ,いくつかのプログラムでその関数群を再利用することが多い。一連の関数群のうち,他のファイルから呼び出されない関数は,そのままでは関数名が重複してしまうことがあり,好ましくない。他のファイルから呼び出されない関数は関数名をそのファイル内でのみ有効にして,ほかのファイルからは見えないようにすることができる。
マルチソースファイル中で,関数にstatic修飾をつけると,その関数は,他のソースファイルからみえなくなる。この機能を用いると関数名の衝突事故を防ぐことが出来る。
1.static宣言された関数の利用例
あるソースファイル「〜.c」で定義している関数のうち,公開する関数はヘッダファイル「〜.h」にプロトタイプ宣言を記述し,公開しない関数はstatic修飾をつける。static宣言された関数名は,そのファイル中でのみ有効になる。このようにすると関数名の衝突を防ぐことが出来る。
もともと「static」は静的の意味であるが,ここでは「local」の意味と解釈した方がよい。
次の例は時間構造体の演算関数群を定義しているソースファイル中で,公開する関数はヘッダファイル「〜.h」にプロトタイプ宣言を記述し,公開しない関数はstatic修飾をつけている。
#include <stdio.h> /*--------------------------------------------- #include <stdio.h>
TOmain.c
#include "timeOperation.h"
int
main()
{
hmstime_t
t1,t2,t3;
double k=2.0,ratio;
char tstr1[32],tstr2[32],tstr3[32];
t1=StrtoTime("2:26:48");
t2=StrtoTime("2:34:50");
TimeToStr(tstr1,t1);
TimeToStr(tstr2,t2);
t3=addTime(t1,t2);
TimeToStr(tstr3,t3);
printf("%s+%s=%s\n",tstr1,tstr2,tstr3);
t3=subtractTime(t1,t2);
TimeToStr(tstr3,t3);
printf("%s-%s=%s\n",tstr1,tstr2,tstr3);
t3=subtractTime(t2,t1);
TimeToStr(tstr3,t3);
printf("%s-%s=%s\n",tstr2,tstr1,tstr3);
t3=multiplyTime(t1,k);
TimeToStr(tstr3,t3);
printf("%s*%f=%s\n",tstr1,k,tstr3);
t3=divideTime(t1,k);
TimeToStr(tstr3,t3);
printf("%s/%f=%s\n",tstr1,k,tstr3);
ratio=divideTime2(t1,t2);
printf("%s/%s=%f\n",tstr1,tstr2,ratio);
ratio=divideTime2(t2,t1);
printf("%s/%s=%f\n",tstr2,tstr1,ratio);
return
0;
}
timeOperation.h
時間の演算を定義する関数群
時間に関する演算として次のものを定義する。
時間+時間→時間
時間-時間→時間
時間*定数→時間
時間/定数→時間
時間/時間→定数
---------------------------------------------*/
typedef
struct {
int sign; /*1 or
-1*/
int hour;
/*時間*/
int min;
/*分*/
double sec; /*秒*/
}
hmstime_t;
hmstime_t addTime(hmstime_t t1, hmstime_t
t2);
/*時間+時間→時間*/
hmstime_t subtractTime(hmstime_t t1, hmstime_t
t2); /*時間-時間→時間*/
hmstime_t multiplyTime(hmstime_t
t1, double k);
/*時間*定数→時間*/
hmstime_t divideTime(hmstime_t t1, double
k);
/*時間/定数→時間*/
double divideTime2(hmstime_t t1, hmstime_t
t2); /*時間/時間→定数*/
hmstime_t
StrtoTime(char
*str);
/*文字列hh:mm:ss→時間*/
void TimeToStr(char *str,hmstime_t
t);
/*時間→文字列hh:mm:ss*/
timeOperation.c
#include "timeOperation.h"
static hmstime_t normalizeTime(hmstime_t
t)
{
int tmp;
double
subsec;
if (t.sign!=-1)
t.sign=1;
tmp=(int)t.sec;
subsec=t.sec-tmp;
t.sec=tmp%60+subsec;
tmp/=60;
t.min+=tmp;
tmp=t.min/60;
t.min%=60;
t.hour+=tmp;
return
t;
}
static double
convertTimetoDouble(hmstime_t t)
{
double
x;
x=t.sec+60.0*t.min+3600.0*t.hour;
if (t.sign==-1)
x=-x;
return x;
}
static hmstime_t convertDoubletoTime(double
x)
{
hmstime_t
time={1,0,0,0};
double subsec;
int tmp;
if (x<0)
{
time.sign=-1;
x=-x;
}
tmp=(int)x;
subsec=x-tmp;
time.sec=tmp%60+subsec;
tmp/=60;
time.min=tmp%60;
time.hour=tmp/60;
return time;
}
hmstime_t
addTime(hmstime_t t1, hmstime_t t2)
/*時間+時間→時間*/
{
double
x1,x2;
x1=convertTimetoDouble(t1);
x2=convertTimetoDouble(t2);
return
convertDoubletoTime(x1+x2);
}
hmstime_t subtractTime(hmstime_t
t1, hmstime_t t2) /*時間-時間→時間*/
{
double
x1,x2;
x1=convertTimetoDouble(t1);
x2=convertTimetoDouble(t2);
return
convertDoubletoTime(x1-x2);
}
hmstime_t multiplyTime(hmstime_t
t1, double k)
/*時間*定数→時間*/
{
double x;
x=convertTimetoDouble(t1);
return
convertDoubletoTime(x*k);
}
hmstime_t divideTime(hmstime_t t1,
double k)
/*時間/定数→時間*/
{
double x;
x=convertTimetoDouble(t1);
return
convertDoubletoTime(x/k);
}
double divideTime2(hmstime_t t1,
hmstime_t t2)
/*時間/時間→定数*/
{
double
x1,x2;
x1=convertTimetoDouble(t1);
x2=convertTimetoDouble(t2);
return
x1/x2;
}
hmstime_t StrtoTime(char
*str)
/*文字列hh:mm:ss→時間*/
{
hmstime_t
time={1,0,0,0};
sscanf(str,"%d:%d:%lf",&time.hour,&time.min,&time.sec);
if (time.hour<0) {
time.sign=-1;
time.hour=-time.hour;
}
return
normalizeTime(time);
}
void TimeToStr(char *str,hmstime_t
t)
/*時間→文字列hh:mm:ss*/
{
char
*format[2]={
"%02d:%02d:%05.2f",
"-%02d:%02d:%05.2f"
};
t=normalizeTime(t);
sprintf(str,format[t.sign==-1],t.hour,t.min,t.sec);
}
実行結果
02:26:48.00+02:34:50.00=05:01:38.00
02:26:48.00-02:34:50.00=-00:08:02.00
02:34:50.00-02:26:48.00=00:08:02.00
02:26:48.00*2.000000=04:53:36.00
02:26:48.00/2.000000=01:13:24.00
02:26:48.00/02:34:50.00=0.948116
02:34:50.00/02:26:48.00=1.054723
2.複数ファイルのプログラミングの一般的な形
一般的には次のようなファイル構成となる。
「〜.h」には,元になる「〜.c」に定義されている関数のプロトタイプ宣言が書いてあり,関数が使われる「〜〜.c」にインクルードされるように使われる。なお,例えばsub3.cに定義されている関数がsub2.cで使われるなら,sub2.cにsub3.hをインクルードする必要がある。
sub1.c,sub2.c,sub3.c内にstaticとされた関数があるが,それらは定義されたファイル中でのみ有効な関数である。
たとえば「staic
int
localfunc1(...)」などは定義されたファイル(sub1.c)中のみ有効な関数となる。それゆえ,sub1.c,sub2.c,sub3.c内に同じ名前のstatic関数があってもかまわない。
main()を含むソース | sub1.c | sub2.c | sub3.c |
#include <...> |
#include <...> |
#include <...> #include "sub2.h" static char buff[128]; static int var1; staic int localfunc1(...) { : } staic int localfunc2(...) { : } int func21(...) { : } int func22(....) { : } : |
#include <...> #include "sub3.h" static int var1; staic int localfunc1(...) { : } staic int localfunc2(...) { : } int func31(...) { : } int func32(....) { : } : |
sub1.h | sub2.h | sub3.h | |
int
func11(...); int func12(...); : |
int
func21(...); int func22(...); : |
int
func31(...); int func32(...); : |