関数

C 言語のソース コードは主に関数 (function) の集まりです。言語によっては「サブルーチン」、「プロシージャ」、「手続き」などの概念がありますが、それらは C ではすべて「関数」です。関数宣言・関数定義の主な構文は次のとおりです。
構文 type name( [args]... ) { statements... } // 関数定義
type name( [args]... ); // 関数プロトタイプ宣言

参照   宣言

関数定義

C の実行コードはすべて関数定義の { } 内に記述します。
void func1() { // 何もしない関数
}
 
int func2() { // int 型の戻り値 3 を返す関数
  return 3;
}
 
int func3() { // 1 から 10 までの合計を返す関数
  int i, r;
  for ( i = 1; i <= 10; i++ )
    r += i;
  return r;
}

関数の中には任意の実行コード (たとえば代入、加減算、ループなど) を記述します。別の関数を呼び出すこともできます。ただし関数の中で別の関数を定義することはできません。

プロトタイプ宣言

関数本体 ({...} の部分) の定義を持たない関数宣言を「関数プロトタイプ宣言」と呼びます。プロトタイプ宣言を行うと、以降のその関数の定義や呼び出しの型がチェックされ、矛盾があると警告が表示されます。複数のソース ファイルでプログラムを作成する場合は、ヘッダー ファイルに各関数のプロトタイプ宣言を記述しておき、定義と呼び出しの間に型の矛盾がないかチェックすることがよくあります。

プロトタイプ宣言がなくても、関数の定義または呼び出しが行われた時点で、その形式に基づいて関数の型が仮定されます。それ以降、その関数が仮定と異なる型で使用されると、警告が表示されます。

関数の戻り値の型を省略すると、既定で int と仮定されます。戻り値のない関数を宣言・定義するには、戻り値の型を void と指定します。
void func1( void ); // 関数プロトタイプ宣言。戻り値なし、引数なし
int func2( float ); // 関数プロトタイプ宣言。戻り値 int、引数 float
void main() { // 関数定義
  int a = func1(); // 警告。戻り値はないはず
  int b = func2( 3.14 ); // 有効
  func1( a ); // 警告。引数はないはず
  func2( a ); // 有効。a が float に変換される
}

関数呼び出し

定義した関数は「<関数名>()」というで呼び出すことができます。引数がある場合は () の中にカンマ (,) で区切って記述します。関数呼び出しの引数の数と型は、その関数の実際の定義に一致する必要があります。名前は一致しなくてかまいません。
func(); // func を呼び出す
a = func(); // func を呼び出して戻り値を a に代入
a = func( b, c ); // func を引数 b と c で呼び出して戻り値を a に代入

引数のスコープ

関数の引数のスコープと生存期間は、局所変数と同様に、関数内に限定されます。また、関数内で引数の値を変更しても、その変更は関数呼び出し側のコードには反映されません。ただし、引数がポインタの場合、そのポイント先の値の変更は、関数呼び出し側にも影響します。
void sub( int a, int* b ) {
  a++;
  (*b)++;
}
void func() {
  int x = 0, y = 0;
  sub( a, &b ); // a の値は変化しないが b の値は 1 増える
}

return 文と戻り値

return 文が実行されると、コード実行は関数呼び出し (の次の文) に戻ります。
void func( int f ) {
  if ( f < 0 )
    return; // f が負なら関数 func をここで終了
  ...
}

関数からは最大 1 つの値を戻り値 (返り値) として返すことができます。戻り値を指定する場合は、return 文を次のように記述します。
構文 return <>
return 3; // 3 を返す
return( 3 ); // 上と同じ
return a + b; // a + b の計算結果を返す

C 言語では関数から複数の値を返すことはできません。関数から複数の値を返したい場合は、一般に次のようにします。

main 関数

構文 int main( int argc, char* argv[] );

プログラムの実行は main 関数から始まります。

一般に main 関数はスタートアップ ルーチンから呼び出され、main 関数の戻り値はプログラムの終了コードになります。

argc には、コマンドラインで指定したパラメータの数 + 1 が渡されます。パラメータを 1 つも指定しないと、1 が渡されます。

argv には、パラメータ文字列の配列が渡されます。通常、argv[0] には実行したプログラム自体のパスが入りますが、本コンパイラでは常に "(pgm-name)" になります。argv[1]argv[argc-1] にパラメータ文字列が格納され、argv[argc] に NULL が格納されます。

MS-DOS のコマンドライン (または Windows のコマンド プロンプト) では、パラメータをスペースで区切って指定します。パラメータにスペース文字を含めるには、パラメータを " " で囲みます。パラメータに「"」自体を含めるには、" " の中で "" と記述します。
mypgm abc "d e f" """gh""" """"
argc = 5
argv[0] =「(pgm-name)」
argv[1] =「abc」
argv[2] =「d e f」
argv[3] =「"gh"」
argv[4] =「"」
argv[5] = NULL

引数の省略記号 (...)

引数の数が不明な場合に使用します。ただし最初の引数には指定できません。
int printf( char*, ... ); // 2 番目以降の引数の型と数は不明
int printf2( ... ); // これはエラー

va_arg も参照してください。

静的関数

関数の宣言または定義の先頭にキーワード static を付けると、その関数はファイル外に公開されません (つまり別のファイルから使用できなくなります)。言い換えると、キーワード static によってスコープがファイル内に限定された局所的な関数を定義できます。同じ名前の関数が複数のファイルで定義されていると、それらの関数が静的でなければリンク時にエラーになりますが、それらの関数が静的であればエラーになりません。

単一の翻訳単位 (ソース ファイル) からなるプログラムでは、関数が静的かどうかは意味を持ちません。
static void local_func();

関数へのポインタ

関数へのポインタを定義できます。
#include <string.h>
int (*pf)( const char*, const char* ); // 関数へのポインタの型 pf を宣言
pf = strcmp; // 関数のアドレスを代入
int a = pf( "1", "2" ); // 関数へのポインタを使って strcmp を呼び出す
int b = (*pf)( "1", "2" ); // 上と同じ意味

ポインタに代入する関数の型が一致しないと、警告が表示されます。
pf = memcpy; // 警告が発生