「C言語/関数」の版間の差分

削除された内容 追加された内容
なお、strcpyは、文字列をコピーするための命令。strcpyを使うには、string.hのインクルードが必要である。
修正。ポインタを使わずともstatic変数でも、各関数ブロックを超えた変数値の共有は出来る。
102 行
 
 
=== 「メソッド」 ===
== ポインタの必要性 ==
「関数」というが、C言語の関数(function)は、数学の関数(function)とは、まったく違う。
このように、C言語の(ユーザーが自分で定義する)「関数」は、かなり特殊なシステムである。そのため、「ポインタ」という機能をつかわないと、あまり価値のある作業が、関数では、できない場合が多い。
 
これが理解時の混乱の原因になるだろうとして、90年代ごろから、Visual C++などの言語では、C言語の関数とほぼ同じ意味で「メソッド」という用語が使われた。
C言語の入門書に書いてあるプログラムで、ポインタを使わなくても利用できる(ユーザー定義)関数は、むしろ珍しいプログラムなのである。画面に文字などを表示するだけなら、ポインタを使わなくても、そのようなアルゴリズムを構築できるので、そのようなプログラムがC言語の入門書の『関数』の章に書かれるのであろう。
 
Visual C++やC#などの言語でいう「メソッド」は、上述のC言語の「関数」と、ほぼ同じ機能、もしくは機能拡張したものである。
なお、「return a;」などのように戻り値をつかって 計算結果の数値を 呼び出しもとの関数に送信したりする方法は、じつは、あまり実用的ではなく、現実には不便な場合が多いのである。なぜなら、
 
:まず、呼び出しもとの どの変数に値を送るかを、呼び出し先のreturnからは指定できないし、(けっして、呼び出しもとの変数aに、数値を代入してくれるわけではない)
 
さらに2010年ごろから、function(ファンクション)に発音の似ている「アクション」の用語が一部のプログラム言語で使用されているが、しかし普及してない。
 
 
== static 変数とポインタの必要性 ==
このように、C言語の(ユーザーが自分で定義する)「関数」は、かなり特殊なシステムである。そのため、「ポインタ」という機能をつかわないと、あまり価値のある作業が、関数では、できない場合が多い
 
実用では、呼び出し先の関数で、呼び出しもとの変数の値も変更したい場合も多く、その場合には、「 static 変数」(静的変数)もしくは「ポインタ」という機能をつかう。
 
static 変数とは、変数の宣言時に
static int x;
などと static をつけて宣言すると、その名前の変数は、どこの変数で呼び出されても、共通のアドレスで管理しているので、呼び出した関数の先で、呼び出し元の関数も書き換えできる機能をもつ。
 
いったい何が「静か」(static)なのか不明であるが、おそらく、関数呼び出し時にもアドレス領域を新規確保しないままでいるという意味で、「静か」なのだろう。
 
 
C言語の入門書での「関数」の章の前半に書いてあるプログラムで、static変数やポインタを使わなくても利用できる(ユーザー定義)関数は、むしろ珍しいプログラムなのである。画面に文字などを表示するだけなら、ポインタを使わなくても、そのようなアルゴリズムを構築できるので、そのようなプログラムがC言語の入門書の『関数』の章に書かれるのであろう。
 
なお、「return a;」などのように戻り値をつかって 計算結果の数値を 呼び出しもとの関数に送信したりする方法は、じつは、あまり実用的ではなく、現実には不便な場合が多いのである。なぜなら、
 
なぜなら、
:まず、呼び出しもとの どの変数に値を送るかを、呼び出し先のreturnからは指定できないし、(けっして、呼び出しもとの変数aなどを指定して、数値を代入してくれるわけではない)
:しかも、その関数が終了してしまうので、ほかにも処理をその関数で続行したい場合に不便であるし、
:しかも、1つの数値しか送れない
など、いろんな欠点がある。
 
220 ⟶ 242行目:
そこで、変数を再利用可能にすることのできる static スタティックという宣言がある。このstaticをつけると、たとえローカル変数でも、関数の終了時に、その変数の値が消去されずにメモリに残りつづけるようになるので、再度その関数を呼び出したときに、前回の(そのstaticのついた変数の)計算結果を再利用できる。
 
「static」とは「静的」などと訳され、表現はいかめしいが、しかしstaticの実態は「関数が終わっても値を保管しとけ」程度の実態でしかない。
 
 
239 ⟶ 261行目:
 
 
一方、すべてのブロックの外側で宣言された変数を* グローバル変数と呼ぶ。の違い
すべてのブロックからアクセスできる変数を「グローバル変数」と呼ぶ。
 
C言語プログラミングでは一般に、コードファイルの冒頭の、どこの関数ブロック内でもない場所で変数宣言をすることにより、グローバル変数として宣言されたことになり、どこの関数からでもアクセスできる。
 
しかし、その変数にアクセスできることと、各関数ブロックの実行時に領域を新規作成しないかは別のことである。
 
なので、グローバル変数といえども、各関数ブロックの計算結果を共有したい場合には、さらに宣言時に static を接頭辞につけて宣言する必要がある。
 
 
グローバル変数は全てのブロックからアクセスできる(ファイル有効範囲)。<ref name="識別子の有効範囲"/>
グローバル変数はプログラムが開始されたときに作成され、
249 ⟶ 280行目:
注意!
グローバル変数の乱用は避けるべきです。
 
理由は、どこからでもアクセスできることでバグの発見が困難になったり、
プログラムの実行中ずっと存在することでメモリの使用効率が落ちたりするからです。
</pre>
 
よく、↑こう言われてるが、かといって main関数 で変数を宣言しても、今度は、main関数が他のどの関数ブロックからでもアクセスできるので、やはりバグの発見が困難になる。
 
 
もし「main関数から関数Aを呼び出して、関数Aからは関数Bと関数Cを呼び出す仕様。関数Bで計算した結果の変数を、関数Cでも利用する。」などのコードが3階層(mainの階層、Aの階層、BとCの階層)に分かれた仕様のプログラムなら、変数を共有したい関数Bと関数Cの共通の呼び出し元である関数Aで変数宣言をしてstatic宣言をするのが、バグ発見をしやすいプログラムになるだろう。
 
 
要するに、上述の例のようにプログラムの関数が幾層にも分かれているとき、変数を共有したい複数の関数ブロックがあれば、その手前の段階の階層で、宣言をすると、バグ発見がしやすくなる。
 
初心者の段階では、幾層もあるプログラムは書かないので、あまり着にする必要が無い。
 
また、main関数しかないプログラムなら(関数が「1階層」しかないなら)、グローバル変数を使わずにmain関数内ですべて変数宣言をする行為は、もしも、宣言したい変数の個数が多い場合には(たとえば30個の変数を宣言する場合を考えてみればいい)、単にmain関数のプログラム内容を見づらくするだけであり、「グローバル変数を使わないようにしよう」という努力があまり役立たない。
 
 
 
* ローカル変数の寿命
関数ブロックの内部で宣言された変数を「ローカル変数」と言う。

ローカル変数は、その関数が終わるときに消えるが、正確に言うと、そのローカル変数を宣言したブロックが終了するときに、そのローカル変数も消去される。<ref>ウェブページ『関数内で寿命が尽きる変数 』 http://9cguide.appspot.com/12-01.html</ref>
 
ブロックとは、記号 { と } とで挟まれた処理単位である。
262 ⟶ 309行目:
 
if文やfor文の{}もブロックと見なされるので、注意が必要である。<ref>ウェブページ『ロベールのC++教室 - 第68章 寿命 -』 http://www7b.biglobe.ne.jp/~robe/cpphtml/html01/cpp01068.html</ref>
 
 
 
=== 関数原型 ===
382 ⟶ 431行目:
しかし、特殊な方法を使うことにより、呼び出しもとの関数に、複数の値を送ることができる。
 
下記に述べるように、少なくとも以下の23つの方法がある。
 
 
==== static変数を使う ====
:(※ 未記述)
 
 
==== ポインタを使う方法 ====
まず、ポインタを使う方法である。しかし、ポインタを使えば、2つ以上の数値を操作する事ができるので、ポインタを使って、呼び出し元関数の複数の値を操作する事ができるので、それを「複数の返却値である」と解釈する事もできる
 
このような事を、「ポインタによる参照渡しの引数を、返却値として用いる」などと言ったりするが、要するにポインタを使って呼び出し元の変数の値を操作するというだけの事であり、あまり深い意味はない。
408 ⟶ 462行目:
 
==== 構造体を使う方法 ====
2つ目の方法として(もうひとつ別の方法として、返却値のデータ型に構造体を使って、
その構造体で複数の返却値を表現する方法もある。