情報処理Ⅱ 2005年11月25日(金)
本日学ぶこと ポインタのポインタ ポインタを使ったプログラミング さまざまな「空」 コマンドライン引数 回文判定(コマンドライン引数から語を獲得) 任意型のビットパターン出力 さまざまな「空」 NULLポインタ void型 ナル文字('\0') 空文
ポインタのポインタ 指し示すものを指し示す 例: char **p; p p[0] p はchar **型 (参考)多次元 配列の模式図
多次元配列とポインタのポインタ 配列とポインタが異なるように,「多次元配列」と「ポインタとポインタ」も異なる. × int a[2][3]; int **p = a; ○ int b[2][3]; int (*q)[3] = b; 一次元配列に限り, ○ int c[2]; int *r = c; a と b は「int [2][3]」型,ただしポインタ値としては「int (*)[3]」型 c は 「int [2]」型,ただしポインタ値としては「int *」型 int *q2[3]; と書くと,これは「int *[3]」型,ポインタ値としては「int **」型
コマンドライン引数 コマンドライン引数とは C言語でコマンドライン引数を獲得するには argv argv[0] argv[1] 例: cc program.c でコンパイルするとき, 「cc」はコマンド名,「program.c」はコマンドライン引数と呼ばれる. C言語でコマンドライン引数を獲得するには main関数を main(int argc, char *argv[ ]) と宣言する. argv はchar **型のポインタ変数 argv argv[0] argv[1] argv[2] = NULL "cc" argc = 2 "program.c"
NULLポインタ NULLは特殊な扱いをする定数であり,空ポインタ定数(null pointer constant)とも呼ばれる. キャスト(明示的な型変換)なしで, 任意のポインタ型オブジェクトへの代入や, 任意のポインタ値との比較が可能 if,for,whileなどの条件式に,ポインタ値が指定可能 真…NULL以外のすべてのポインタ値 偽…NULL
コマンドライン引数とargv(1) argv argv[0] argv[1] argv[2] = NULL "./commandline" 「./commaneline abc」を実行したときの 初期状態 argv argv[0] argv[1] argv[2] = NULL "./commandline" "abc"
コマンドライン引数とargv(2) argv argv[-1] argv[0] argv[1] = NULL "./commandline" としたとき argv argv[-1] argv[0] argv[1] = NULL "./commandline" "abc"
コマンドライン引数とargv(3) argv argv[-2] argv[-1] argv[0] = NULL さらに argv++; としたとき argv argv[-2] argv[-1] argv[0] = NULL "./commandline" "abc" *argv はNULL(偽)
回文判定にコマンドライン引数を 仕様 例 入力は,コマンドライン引数から獲得する. コマンドライン引数の各文字列が回文になっていれば「Yes」を,そうでなければ「No」を出力する. あとは前述の回文判定と同じ. 例 ./palindrome2 12321 123321 noon Noon 12321 : Yes 123321 : Yes noon : Yes Noon : No
ここまでのまとめ ポインタは「型 *変数名;」で宣言し,式の中では その参照先を「*変数名」により得ることができる. 値として参照するときは,ポインタ変数でも配列変数でも同じ書式. 変数宣言により生じる効果は,配列とポインタとで異なる. ポインタ値の加減算はポインタ変数の得意技. コマンドライン引数は,ポインタのポインタで獲得できる.
任意型のビットパターン出力:仕様など 仕様 例 出力したいオブジェクトの型や値は,プログラムの中で与える. 各ビットは上位から下位の順に出力する. 1バイトごとに空白文字を置いて出力する. 例 入力: int x = -40; 出力: 11011000 11111111 11111111 11111111 入力: float f = 40; 出力: 00000000 00000000 00100000 01000010
任意型のビットパターン出力:方針 float f = 40; char *p = (char *)&f; とすると,*p, *(p + 1), ..., *(p + sizeof(float)-1) は,fの「バイトごとの」中身である. 1バイトのビットパターンを求めるプログラムを活用して, バイトごとに出力すればいい! float f : p p+1 p+2 p+3 char *p : は1バイト
ポインタのキャストが必要な理由 float f = 40; としたとき, p1+1 float *p1 : float f : p3+1 char *p2 = &f; は,型が合わない. char *p3 = (char *)&f; とすればうまくいく. float *p1 : p1+1 は1バイト char *p3 : p3+1 float f :
ビットパターン出力 float f = 40; の結果 バイトごとに逆順に出力すると fを-10から10まで変えてみると 00000000 00000000 00100000 01000010 バイトごとに逆順に出力すると 01000010 00100000 00000000 00000000 fを-10から10まで変えてみると
「空」とプログラム プログラミングと関係のない「空」の例 Cにおける「空」とは,「それは空である」,「空の…がある」などを明示するための概念 「部屋がない」と「空室がある」は違う. 空集合φ={}と,空集合のみからなる集合{φ}={{}}は違う. Cにおける「空」とは,「それは空である」,「空の…がある」などを明示するための概念
void型 voidは「何もない」や「無効な値」を表す型名 用途 × void x; ○ void *x; ただし,sizeof(void)は0ではなく1 用途 関数が引数や戻り値を持たないことを明示するとき void exit(int status); void procedure(void); 任意のポインタ型を表現するとき void *p; void *malloc(size_t size); プログラムを終了するライブラリ関数.通常,exit(0); もしくは exit(1); のいずれかで呼び出す.
ナル文字 '\0' をナル文字(null character)という. 文字列の末尾につく. ○ '\0' == 0 × '\0' == '0' × '\0' != NULL 文字列の末尾につく. ナル文字は,文字列の字数には数えられないが,char型の 1要素分(1バイト分)を占める.
空文 「式;」を式文という.式文から式を取り除いたものを空文(null statement)という. 用途 'a' 'b' 'c' 'd' 「{}」は,空ブロックと呼ばれる. 用途 for文の初期化,条件,増分の省略 for (;;) ... 反復の処理 for (p = "abcdef"; *p && *p != 'c'; p++) ; 'a' 'b' 'c' 'd' 'e' 'f' '\0' p
まとめ int main(int argc, char *argv[])で,コマンドライン引数(文字列の配列)を獲得できる. ポインタ型の値は,キャスト演算子で任意のポインタ型に変換できる. 文字列の走査には,char *型のポインタ変数を活用するとよい. 空ポインタ定数のNULL,void型,ナル文字,空文といった「空(null, empty, void)」の概念がある.
第1回レポートについて 配布資料の通り 提出は,来週金曜日(12月2日)の授業開始時 配点は,10点 演習室等でプログラムを打ち込み,実行すること