C言語入門

1
C言語入門
第15週
プログラミング言語Ⅰ(実習を含む。),
計算機言語Ⅰ・計算機言語演習Ⅰ,
情報処理言語Ⅰ(実習を含む。)
2
補足
return 文
return 戻り値;
• 関数から抜けて呼び出し元へ戻り値を渡す
return_test1.c
int sub()
{
return 123;
printf("hello\n");
}
return文を実行すると
呼び出し元に戻るので
それ以降の文は
実行されない
void main()
{
int x = sub();
printf("%d\n", x);
}
return文に与えた値が
関数の戻り値になり
演算に使用される
mintty + bash + GNU C
$ gcc return_test1.c && ./a
123
return 文
• 戻り値の型は必要に応じて適切な型を選ぶ
return_test2.c
例えばもし
浮動小数点数の値を
戻したいなら
戻り値の型は
doubleでないといけない
int sub()
{
return 1.23;
}
この例では戻り値の型はintなので
return文にdoubleを与えても
戻り値はint型にキャストされるので
整数になる
void main()
{
double = sub();
printf("%f\n", x);
}
mintty + bash + GNU C
$ gcc return_test2.c && ./a
1.000000
5
教科書 pp.265-272., [1] pp.139-144., 講義資料第7週pp.21-22.,第11週pp.24-27.
コマンドライン引数
第13週pp.4-10.
• char *argv[] は char* 型の配列
mintty + bash
正確には
関数の引数で最初の [] は
* と同じだったので
char *argv[] は
char **argv と同じ
つまり
char 型へのポインタへのポインタ
$ ./argtest a b "c d" "e\"f"
argc = 5
argv[0] = "./argtest"
argv[1] = "a"
argv[2] = "b"
argv[3] = "c d"
argv[4] = "e"f"
argv[1]
argv[2]
argv[3]
argv[4]
'a'
'\0'
'b'
'\0'
'c'
' '
'd'
'\0'
'e'
'"'
f
'\0'
データ型の制限: <limits.h>
CHAR_BIT
CHAR_MAX
char 型のビット数
UCHAR_MAX または SCHAR_MAX
CHAR_MIN
0 または SCHAR_MIN
SCHAR_MIN, SHRT_MIN, INT_MIN, LONG_MIN
signed の char, short, int, long の最小値
SCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX
signed の char, short, int, long の最大値
UCHAR_MAX, USHRT_MAX, UINT_MAX, ULONG_MAX
unsigned の char, short, int, long の最大値
なお unsigned 型は負の数がないので最小値は 0 である
データ型の制限: <float.h>
FLT_RADIX, DBL_RADIX
指数表現の基数
FLT_DIG, DBL_DIG
精度の10進桁数
FLT_MANT_DIG, DBL_MANT_DIG
仮数部における基数(RADIX)の桁数
FLT_EPSILON, DBL_EPSILON
1.0 + 𝑥 ≠ 1.0となる最小の𝑥
FLT_MAX, DBL_MAX
float, double の最大値
FLT_MIN, DBL_MIN
float, double の正規化された最小の浮動小数値
FLT_MAX_EXP, DBL_MAX_EXP
RADIX 𝑛 − 1が表現可能な𝑛の最大値
FLT_MIN_EXP, DBL_MIN_EXP
10𝑛 を正規化された浮動小数値として表現可能な𝑛の最小値
この授業で扱わなかったこと
• 構造体と共用体: struct, union
• 型定義: typedef
• 可変長引数: <stdarg.h>
• va_list, va_start, va_arg, va_end
• 非局所ジャンプ: <setjmp.h>
• シグナル処理: <signal.h>
9
C言語の開発支援ツール
10
分割コンパイル
• ファイルが多くなるとコンパイルが大変
mintty + bash + GNU C
$ gcc strtoi_test.c strtoi.c strtosign.c strtobase.c basetoint.c base36toint.c
$
cmd + Borland C++
>bcc32 strtoi_test.c strtoi.c strtosign.c strtobase.c basetoint.c base36toint.c
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
strtoi_test.c:
一度実行すれば
strtoi.c:
strtosign.c:
カーソルキーの上下で
strtobase.c:
コマンドの実行履歴から
basetoint.c:
base36toint.c:
選べるが、最初が面倒
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
1ファイルしか変更してないのに
全ファイルコンパイルし直すのは非効率
11
make コマンド
• 依存関係を記述し必要な処理だけ行う
• Makefile に依存関係と作成方法を記述する
Makefile.cygwin.strtoi_test,1
all: strtoi_test.exe
strtoi_test.exe: strtoi_test.c strtoi.c strtosign.c strtobase.c basetoint.c base36toint.c
$(CC) -o $@ $^
clean:
-rm strtoi_test.exe
作成するファイル: 材料のファイル ...
タブ...→作成方法
Makefile.bcc32.strtoi_test
all: strtoi_test.exe
strtoi_test.exe: strtoi_test.c strtoi.c strtosign.c strtobase.c basetoint.c base36toint.c
$(CC) strtoi_test.c strtoi.c strtosign.c strtobase.c basetoint.c base36toint.c
clean:
-DEL strtoi_test.exe *.obj *.tds
12
make コマンド
• make と打つだけで自動的にコンパイル
mintty + bash + GNU C
$ make -f Makefile.cygwin.strtoi_test,1
cc -o strtoi_test.exe strtoi_test.c strtoi.c strtosign.c strtobase.c basetoint.c base36toint.c
cmd + Borland C++
>make -f Makefile.bcc32.strtoi_test
MAKE Version 5.2 Copyright (c) 1987, 2000 Borland
bcc32 strtoi_test.c strtoi.c strtosign.c strtobase.c basetoint.c base36t
oint.c
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
strtoi_test.c:
strtoi.c:
strtosign.c:
strtobase.c:
basetoint.c:
base36toint.c:
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
13
make コマンド
• 依存関係の記述
作成するファイル: 材料のファイル ...
タブ...→作成方法
Makefile.cygwin.strtoi_test,2
all: strtoi_test.exe
strtoi_test.exe: strtoi_test.o strtoi.o strtosign.o strtobase.o basetoint.o base36toint.o
$(CC) -o $@ $^
strtoi_test.o: strtoi_test.c myfunc_week10.h
strtoi.o: strtoi.c myfunc_week10.h myfunc_week11.h myfunc_week12.h
strtosign.o: strtosign.c myfunc_week12.h
strtobase.o: strtobase.c myfunc_week12.h
basetoint.o: basetoint.c myfunc_week11.h
標準的な作成方法で良い場合は
base36toint.o: base36toint.c myfunc_week11.h
作成方法は省略出来る
clean:
-rm strtoi_test.exe strtoi_test.o strtoi.o strtosign.o strtobase.o basetoint.o base36toint.o
14
make コマンド
• 依存関係の解決
コンパイルが完了しているので
改めてコンパイルする
必要がなかった
mintty + bash + GNU C
$ make -f Makefile.cygwin.strtoi_test,2
直前に削除したため改めて
cc
-c -o strtoi_test.o strtoi_test.c
コンパイルが必要になった
cc
-c -o strtoi.o strtoi.c
cc
-c -o strtosign.o strtosign.c
ファイルだけ処理し直して
cc
-c -o strtobase.o strtobase.c
てくれている
cc
-c -o basetoint.o basetoint.c
cc
-c -o base36toint.o base36toint.c
cc -o strtoi_test.exe strtoi_test.o strtoi.o strtosign.o strtobase.o basetoint.o base36toint.o
$ make
make: Nothing to be done for 'all'.
$ rm strtosign.o
$ make
cc
-c -o strtosign.o strtosign.c
cc -o strtoi_test.exe strtoi_test.o strtoi.o strtosign.o strtobase.o basetoint.o base36toint.o
15
make コマンド
• 依存関係の解決
• 必要に応じて適宜作成方法を実行する
• 例:
• 材料のファイルが不足している場合
• 作成するファイル(旧)、材料のファイル(新)の場合
16
make コマンド
• 同じmakeという名前が付いていて基本は同じ
だが方言があり、細かい違いがある
•
•
•
•
•
•
Wikipedia / make
GNU Make
Embarcadero / MAKE
JM / make (1)
FreeBSD 9.0-RELEASE-K / make (1)
MSDN / NMAKE Reference
17
その他のビルドツール
• Autotools
• autoconf, automake, libtool の総称
• UNIX 系のソフトウェアでは標準的なビルドツール
• 以下の標準的な手順でビルド出来るようになる
mintty + bash + GNU C
$ ./configure
$ make
$ make install
• 書籍
• GNU AUTOCONF, AUTOMAKE, AND LIBTOOL
https://sourceware.org/autobook/ (無料オンライン版)
• Wikipedia / Autotools
18
その他のビルドツール
• CMake - http://www.cmake.org/
• マルチプラットフォームな Makefile 作成ツール
• Wikipedia / CMake
19
教科書pp.203-206.
ライブラリの自作
• 標準ライブラリ関数はアーカイブやライブラリ
と呼ばれる複数のオブジェクトファイルを1つ
にまとめたファイルとして提供されている
• cygwinでは/usr/lib/libc.a等
• Borland C++ではC:\boland\bcc32\Lib\cw32.lib等
• 標準ライブラリはコンパイル時に自動的にリ
ンクされる
• 但し <math.h> 等は -lm 等として明示的に
/usr/lib/libm.aをリンクする必要がある場合もある
20
ライブラリの自作
• 複数のオブジェクトファイルを1つのファイルにまとめる
にはアーカイバやライブラリアンと呼ばれるツールを
用いる
• JM / ar (1)
• 作成方法:
ar q ライブラリ名 オブジェクトファイル名 ...
• embarcadero / ライブラリマネージャ TLIB.EXE
• 作成方法:
tlib ライブラリ名 -+オブジェクトファイル名 ...
21
ライブラリの自作(Cygwin)
• 複数のオブジェクトファイル(.oファイル)を1つ
の.aファイルにまとめる
• まとめたファイルをアーカイブ(archive)または
スタティックライブラリ(static library)と呼ぶ
mintty + bash + GNU C
$ gcc -c strtoi.c strtosign.c strtobase.c basetoint.c base36toint.c
$ ar q myfunc.a strtoi.o strtosign.o strtobase.o basetoint.o base36toint.o
ar: myfunc.a を作成しています
$ gcc strtoi_test.c myfunc.a
必要な .o ファイルを
myfunc.a から探してリンクし
実行ファイルを作成
複数の .o ファイルをまとめた
.a ファイルの作成
22
ライブラリの自作(Borland C++)
• 複数のオブジェクトファイル(.objファイル)を1
つの.libファイルにまとめる
• まとめたファイルをライブラリと呼ぶ
cmd + Borland C++
>bcc32 /c strtoi.c strtosign.c strtobase.cbasetoint.c base36toint.c
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
strtoi.c:
複数の .o ファイルをまとめた
必要な .obj ファイルを
strtosign.c:
strtobase.c:
.lib ファイルの作成
myfunc.lib から探してリンクし
basetoint.c:
実行ファイルを作成
base36toint.c:
>tlib myfunc.lib -+strtoi.obj -+strtosign.obj -+strtobase.obj -+basetoint.obj -+base36toint.obj
TLIB 4.5 Copyright (c) 1987, 1999 Inprise Corporation
>bcc32 strtoi_test.c myfunc.lib
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
strtoi_test.c:
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
23
ライブラリの自作
• make によるアーカイブの作成
Makefile.cygwin.myfunc.a
all: myfunc.a
myfunc.a: strtoi.o strtosign.o strtobase.o basetoint.o base36toint.o
$(AR) q $@ $^
strtoi_test.o: strtoi_test.c myfunc_week10.h
strtoi.o: strtoi.c myfunc_week10.h myfunc_week11.h myfunc_week12.h
strtosign.o: strtosign.c myfunc_week12.h
strtobase.o: strtobase.c myfunc_week12.h
basetoint.o: basetoint.c myfunc_week11.h
base36toint.o: base36toint.c myfunc_week11.h
clean:
-rm myfunc.a strtoi.o strtosign.o strtobase.o basetoint.o base36toint.o
24
ライブラリの自作
• make によるアーカイブの作成
mintty + bash + GNU C
$ make -f Makefile.cygwin.myfunc.a
cc
-c -o strtoi.o strtoi.c
cc
-c -o strtosign.o strtosign.c
cc
-c -o strtobase.o strtobase.c
cc
-c -o basetoint.o basetoint.c
cc
-c -o base36toint.o base36toint.c
ar q myfunc.a strtoi.o strtosign.o strtobase.o basetoint.o base36toint.o
ar: myfunc.a を作成しています
教科書pp.188-189.
ユニットテスト(単体テスト)
• 標準ライブラリヘッダ <assert.h>
• assert マクロの利用
• ユニットテストツールの利用
• CUnit
http://cunit.sourceforge.net/
25
26
assert マクロ
void assert(int expression)
• expression がゼロの場合以下のメッセージを
stderr に出力し abort する
Assertion failed: expression, file filename, line nnn
• <assert.h>をインクルードする時点で NDEBUG
マクロが定義されていると assert マクロは無
視される
• ユニットテストだけでなくデバッグ時のみ有効に
する不正値のチェック等でも利用される
27
assert マクロ
• 専用のテストルーチンで使用した例
is_leap_year_assert.c
is_leap_year_assert.c
void test_leap_year()
{
assert(is_leap_year(-400)
assert(is_leap_year(- 56)
assert(is_leap_year(- 4)
assert(is_leap_year(
0)
assert(is_leap_year(
4)
assert(is_leap_year( 56)
assert(is_leap_year( 400)
assert(is_leap_year(1996)
assert(is_leap_year(2000)
assert(is_leap_year(2004)
}
void test_normal_year()
{
assert(is_leap_year(-300)
assert(is_leap_year(-200)
assert(is_leap_year(-100)
assert(is_leap_year(- 3)
assert(is_leap_year(- 2)
assert(is_leap_year(- 1)
assert(is_leap_year(
1)
assert(is_leap_year(
2)
assert(is_leap_year(
3)
assert(is_leap_year( 100)
assert(is_leap_year( 200)
assert(is_leap_year( 300)
assert(is_leap_year(1900)
assert(is_leap_year(1997)
assert(is_leap_year(1998)
assert(is_leap_year(1999)
assert(is_leap_year(2001)
assert(is_leap_year(2002)
assert(is_leap_year(2003)
}
is_leap_year_assert.c
int main()
{
test_leap_year();
test_normal_year();
return EXIT_SUCCESS;
}
==
==
==
==
==
==
==
==
==
==
1);
1);
1);
1);
1);
1);
1);
1);
1);
1);
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
==
0);
0);
0);
0);
0);
0);
0);
0);
0);
0);
0);
0);
0);
0);
0);
0);
0);
0);
0);
28
assert マクロ
• 専用のテストルーチンで使用した例
• エラーがなければ何も起きない
mintty + bash + GNU C
$ gcc is_leap_year_assert.c is_leap_year_func_4_2.c && ./a
• エラーがあるとそこで実行が中断する
mintty + bash + GNU C
$ gcc is_leap_year_assert.c is_leap_year_func_4_2.c && ./a
assertion "is_leap_year( 0) == 1" failed: file "is_leap_year_assert.c", line 10,
function: test_leap_year
Aborted (コアダンプ)
29
CUnit
• 専用のテストルーチンを作成して使用
is_leap_year_cunit.c
is_leap_year_cunit.c
static CU_TestInfo test_is_leap_year[] = {
{"leap year",
test_leap_year},
{"normal year", test_normal_year},
CU_TEST_INFO_NULL,
};
void test_leap_year()
{
CU_ASSERT_EQUAL(is_leap_year(-400),
CU_ASSERT_EQUAL(is_leap_year(- 56),
CU_ASSERT_EQUAL(is_leap_year(- 4),
CU_ASSERT_EQUAL(is_leap_year(1996),
CU_ASSERT_EQUAL(is_leap_year(2000),
CU_ASSERT_EQUAL(is_leap_year(2004),
}
static CU_SuiteInfo suites[] = {
{"is_leap_year test", NULL, NULL, test_is_leap_year},
CU_SUITE_INFO_NULL,
};
int main()
{
CU_initialize_registry();
CU_register_suites(suites);
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
CU_cleanup_registry();
return EXIT_SUCCESS;
}
1);
1);
1);
1);
1);
1);
is_leap_year_cunit.c
void test_normal_year()
{
CU_ASSERT_EQUAL(is_leap_year(-300),
CU_ASSERT_EQUAL(is_leap_year(-200),
CU_ASSERT_EQUAL(is_leap_year(-100),
CU_ASSERT_EQUAL(is_leap_year(- 3),
CU_ASSERT_EQUAL(is_leap_year(2002),
CU_ASSERT_EQUAL(is_leap_year(2003),
}
0);
0);
0);
0);
0);
0);
30
CUnit
• 専用のテストルーチンを作成して使用
• ユニットテストの達成状況がレポートされる
mintty + bash + GNU C
$ gcc is_leap_year_cunit.c is_leap_year_func_4_2.c -lcunit && ./a
CUnit - A unit testing framework for C - Version 2.1-2
http://cunit.sourceforge.net/
Suite: is_leap_year test
Test: leap year ...passed
Test: normal year ...passed
Run Summary:
Type
suites
tests
asserts
Elapsed time =
Total
1
2
29
0.000 seconds
Ran Passed Failed Inactive
1
n/a
0
0
2
2
0
0
29
29
0
n/a
31
差分パッチツール
• diff : 差分比較、パッチ作成ツール
• JM / diff (1)
• Wikipedia / diff
単一ファイルのパッチの作成
$ diff -c myfile.orig myfile > myfile.patch
ディレクトリ以下のパッチの作成
$ diff -crN mydir.orig mydir > mydir.patch
• patch : 差分適用(パッチ適用)ツール
• JM / patch (1)
• Wikipedia / patch
パッチの適用
$ patch < myfile.patch
カレントディレクトリへのパッチの適用
$ patch -p0 -d. < mydir.patch
32
バージョン管理ツール
• RCS
• Wikipedia / Revision Control System
• CVS
• Wikipedia / Concurrent Version System
• Subversion
• Wikipedia / Apache Subversion
• Mercurial
• Wikipedia / Mercurial
• Bazaar
• Wikipedia / Bazaar
• git
• Wikipedia / git
過去の改変の記録を残したり
複数人で共同で作業する際に
役立つ
github の登場で
人気になっている
33
参考文献
• [1] B.W.カーニハン/D.M.リッチー著 石田晴久
訳、プログラミング言語C 第2版 ANSI 規格準
拠、共立出版(1989)
おつかれさまでした。
来週の試験です。しっかり復習しておきましょう。
おしまい
お
か
だ