アプリ版:「スタンプのみでお礼する」機能のリリースについて

どうもこんにちは
C言語でプログラムを作っています。

複数のファイルから1つのプログラムを作っていますが、あるファイルで実装した関数を別のファイルから使用する際、単にプロトタイプ宣言を行うだけでなく、extern が必要なのでしょうか?

今までは extern を使用せず、以下のように書いてました。
// main.c ファイル
int func_sub();
int func_main()
{
return func_sub() * 2;
}

// sub.c ファイル
int func_sub()
{
return 10;
}

これは extern を使用して、このように書かないとだめなのでしょうか?
// main.c ファイル
extern int func_sub(); // このexternは必要?
int func_main()
{
return func_sub() * 2;
}

// sub.c ファイル
int func_sub()
{
return 10;
}

大域変数を他のファイルでも使用する場合はexternが必要ですが、関数に関してもexternを使用しなければならないのでしょうか?

A 回答 (2件)

★『extern』をつけないと『extern』したのと同じになります。


>大域変数を他のファイルでも使用する場合はexternが必要ですが、
>関数に関してもexternを使用しなければならないのでしょうか?
 ↑
 つけた方が分かりやすいと思います。
 私はヘッダのプロトタイプ宣言や関数定義の時には『extern』や『static』を
 付けて分かりやすくしています。関数定義の時に『extern』をつけておくと
 あとで文字列の『extern』を含む行を取り出せば簡単にプロトタイプ宣言を
 作成できるために関数定義の時も付けます。
・関数定義などでは『extern』、『static』を省略するとすべて『extern』に
 なるため記述しなくても構いません。
 ヘッダのプロトタイプ宣言にも『extern』を省略が可能です。
 グローバル変数の場合は『extern』をつけた方がその変数の宣言と定義を
 見分けられるためにつけた方が良いです。
・以上。参考に。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

省略可能ということなので、既存のコードにスタイルをあわせようと思います。

お礼日時:2007/10/11 09:39

結論からいうと、extern指定子は不要ですが、付けた方が若干ケアレスミスの検出能力は上がります。



記憶クラス指定子無しで宣言した関数は、同じ翻訳単位内で、記憶クラス指定子を伴った同じ関数の宣言がない限り、外部結合になります。
具体的には、

extern void foo(void);
static void bar(void);

void foo(void); /* ← 外部結合 */
void bar(void); /* ← 内部結合 */

のように、同じ関数を複数宣言すると、相互に補完しあう仕様なのです。
そのため、もしextern指定子を付けていないと、

void foo(void); /* ← 外部結合のつもり */

static void foo(void) {} /* 内部結合として定義 */

int main()
{
 foo(); /* 他の翻訳単位で定義されたfooを呼び出したつもりが、そうならない */
 return 0;
}

といった(レアケースでしょうが)失敗を検出できなくなります。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

趣味で作成しているコードにはexternをつけていなかったのですが、仕事で変更しているコードで、既存のコードにexternが付いていたり、付いていなかったりして ( ̄_J ̄)ん? となりました。
省略ができるということなので、付けるかつけないかは既存のコードにあわせようと思います。

お礼日時:2007/10/11 09:43

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!