「C言語/中級者向けの話題」の版間の差分
削除された内容 追加された内容
→再帰を使って2進数表示: paiza.io タグ: 2017年版ソースエディター |
マークアップ修正 タグ: 2017年版ソースエディター |
||
26 行
for (int i = 0; i < sizeof a / sizeof *a; i++)
</syntaxhighlight>
の <syntaxhighlight lang="c" inline>sizeof a / sizeof *a</syntaxhighlight> は、「配列の要素数」を得る時のイディオムです。
{{コラム|配列の一括代入|2=この節で触れたように、C言語では配列同士の代入は出来ません。が、構造体同士の代入はできます。
84 行
</syntaxhighlight>
のようにプログラムを実行した場合、example.exeプログラムのmain関数に対して、「example.exe」、「ABC」、「DEF」、「GHI」という4個の文字列が渡される。
プログラム仮引数を利用するには、ソースコードのmain関数に
179 ⟶ 176行目:
inline関数は、その関数を呼び出した部分に展開して直接埋め込む。
関数呼び出しにかかる処理を短縮することができるが、コードを複数の部分に展開するためファイルサイズが大きくなる。
;inline関数の使用例:<syntaxhighlight lang="C">
#include <stdio.h>
inline int function(int a, int b)
{
return a + b;
}
int main(void){
int r = function(1,2);
}
</syntaxhighlight>
200 ⟶ 194行目:
_Noreturn関数指定子は、関数が呼び出し元に戻らないことを示します。
_Noreturn関数指定子と<stdnoreturn.h>ヘッダファイルは、C11で追加されました<ref>『ISO/IEC 9899:2011』p.91「6.7.4 Function specifiers」</ref>。
:<syntaxhighlight lang="C">
_Noreturn void f (void)
{
210 ⟶ 204行目:
=== 関数の応用 ===
==== 関数へのポインタ ====
関数へのポインタとは、ある関数のメモリアドレスを格納し、その関数に間接的にアクセスする方法です。
関数へのポインタは、次のような場合に使われる。▼
ひとつは、関数を呼び出す際に、関数へのポインタを引数として渡し、呼び出した関数の内部で、関数へのポインタが指す関数を実行する場合。
もうひとつは、関数へのポインタの配列をつくり、if文や、switch文で関数を呼び出すのをやめ、コードを単純にする場合。▼
関数へのポインタは、▼
▲次のような場合に使われる。
▲もうひとつは、関数へのポインタの配列をつくり、
関数へのポインタの宣言の記述は次のようになっている。
229 ⟶ 215行目:
</syntaxhighlight>
この宣言では、代入する関数と同じ返却値のデータ型と引数のリストを指定する必要がある。▼
また、演算子の優先順位のため、「*関数へのポインタ名」を囲う「()」を省略はできない。▼
▲代入する関数と同じ返却値のデータ型と引数のリストを指定する必要がある。
▲「*関数へのポインタ名」を囲う「()」を省略はできない。
関数のメモリアドレスを関数へのポインタに格納する記述は次のようになっている。
:<syntaxhighlight lang="C">▼
▲<syntaxhighlight lang="C">
</syntaxhighlight>
関数名の後ろに、「()」はいらないことに注意。
関数へのポインタを使って、間接的に関数を呼び出すには、次のように記述します。
<syntaxhighlight lang="C">
270 ⟶ 251行目:
</syntaxhighlight>
;関数へのポインタの配列:<syntaxhighlight lang="C">
#include <stdio.h>
299 ⟶ 279行目:
</syntaxhighlight>
==== 再帰的呼出し ====
再帰
典型的な用途として、数学の階乗(5×4×3×2×1のような計算)などが、よくあげられる。
再帰的呼出しに向いた計算に再帰的呼出しを使うと、ソースコードを簡潔に書ける場合がある。
ただし、再帰的呼出しではハードウェア資源的には弱点があり、スタック
そのため、再帰的呼出しで桁数の多すぎる計算などをすると、与えられたスタック領域を使いはたてしまうと異常終了などのエラーを引きおこす場合もある。 これは、いわゆる「スタック・オーバーフロー」(stack overflow)というエラーの一種です。 ▲//例 再帰を使った階乗の計算
#include <stdio.h>
339 ⟶ 305行目:
}
</syntaxhighlight>
この例では再帰的呼出しを使って、入力された整数の階乗を計算している。
3を入力した場合、処理の流れは以下のようになる。
353 ⟶ 319行目:
</syntaxhighlight>
===== 再帰的呼出しを使って2進数表示 =====
;[https://paiza.io/projects/jyBYGklf_W7x1M3gKXjyVA?language=c 再帰的呼出しを使って2進数表示]:<syntaxhighlight lang="C" highlight="6,11"line>
#include <stdio.h>
379 ⟶ 345行目:
print_binary は、リエントラントでない関数 puts と putchar を呼び出しているのでリエントラントでは有りませんが、問題なく再帰呼び出しが行なえます。
このように、再帰可能性(Recursivity)と再入可能性(Reentrancy)は別個の概念で、再入可能性(Reentrancy)はマルチスレッドやシグナルハンドラーで問題になります。
== 構造体のビットフィールド ==
|