1 C言語入門 第6週 プログラミング言語Ⅰ(実習を含む。), 計算機言語Ⅰ・計算機言語演習Ⅰ, 情報処理言語Ⅰ(実習を含む。) 2 第3週資料の復習 1次元配列 3 教科書 pp.85-108. 配列変数 • 同じ変数名で複数の要素を管理する char a[10]; // 要素数10のchar型変数の宣言 初期値式が与えられなかった場合、値は不定 ? ? ? ? a[0] a[1] a[2] a[3] ? ... 要素数10の添え字付き変数 a[9] [1] pp.103-104., p.273. 4 教科書 pp.85-108. 配列変数 • 配列変数の要素への代入 char a[10]; // 要素数10のchar型変数の宣言 a[0] = 'a'; // 0番目の要素へ代入 宣言後の代入 初期値式が与えられなかったので、値は不定 'a' ? ? ? a[0] a[1] a[2] a[3] ? ... 要素数10の添え字付き変数 a[9] [1] pp.103-104., p.273. 5 教科書 pp.85-108. 配列変数 • 添え字は値が取れれば変数や数式でも良い int i = 1; char a[10]; // 要素数10のchar型変数の宣言 a[i + 1] = 'a'; // 2番目の要素へ代入 ? ? 'a' ? a[0] a[1] a[2] a[3] ? ... 要素数10の添え字付き変数 a[9] [1] pp.103-104., p.273. 6 教科書 pp.85-108. 配列変数 • 確保した領域外はアクセスは禁止 char a[10]; // 要素数10のchar型変数の宣言 short b = 0x1234; a[10] = 'a';// 宣言された領域外へのアクセス ? ? ? ? a[0] a[1] a[2] a[3] ここに書き込むと何が起こるか分からない 0x1234 ? 'a' b a[9] a[10] ... 他の変数が使っていたらその値を壊してしまう 要素数10の添え字付き変数 [1] pp.103-104., p.273. 7 教科書 pp.85-108. 配列変数 • 初期値式による配列変数の初期化 char a[10] = {'a', 'b'}; //初期値式付きの //要素数10のchar型変数の宣言 初期値式による初期化 初期値式が要素数より少ない場合、残りは0で初期化 'a' 'b' 0 0 a[0] a[1] a[2] a[3] 0 ... 要素数10の添え字付き変数 a[9] [1] pp.103-104., p.273. 8 教科書 pp.85-108. 配列変数 • 初期値式による配列変数の初期化 char a[] = {'a', 'b'}; //初期値式付きで //要素数を省略したchar型変数の宣言 初期値式による初期化 'a' 'b' a[0] a[1] 初期値式の要素数分確保される [1] pp.103-104., p.273. 9 教科書 pp.85-108. 配列変数 • 文字列による初期化(要素数指定) char a[10] = "ab"; 文字列と文字列終端の'\0' //文字列による初期値付きの //要素数10のchar型変数の宣言 初期値式が要素数より少ない場合、残りは0で初期化 'a' 'b' 0 0 a[0] a[1] a[2] a[3] 0 ... 要素数10の添え字付き変数 a[9] [1] pp.103-104., p.273. 10 教科書 pp.85-108. 配列変数 • 文字列による初期化(要素数自動決定) char a[] = "ab";//文字列による初期値付きで //要素数を省略したchar型変数の宣言 文字列と文字列終端の'\0' 'a' 'b' 0 a[0] a[1] a[2] 文字列の文字数+文字列終端'\0'の1文字分の要素 [1] pp.103-104., p.273. 11 変数の初期化 • 明示的な初期化がない場合 • 外的変数、静的変数→0 • 自動変数、レジスタ変数→不定 • 初期化する場合 • 外的変数、静的変数←定数式でのみ初期化可 • コンパイル時に1度だけ初期化される • 自動変数、レジスタ変数←任意の式で初期化可 • 実行時にブロック毎に初期化される [1] pp.103-104., p.273. 12 配列変数の初期化 • 要素数を与えない場合 • 初期値式の数で配列のサイズが決まる • 要素数を与えた場合 • 初期値式を与えない場合 • 値は不定 • 初期値式を与える場合 • 要素数を超えるとエラー • 要素数に足りない部分は0で初期化される [1] pp.103-104., p.273. 13 配列の初期値と配列の初期化の範囲 配列の初期化についての確認 14 確認: a の値はどうなるか?(1/5) • array_ex1.cを実行し以下の事を確認しなさい • s1: そのまま実行するとどうなるか? • s2: 6行目の初期化だけアンコメント(途中の/*と*/ を削除)するとどうなるか? • s3: 7行目だけアンコメント(先頭の//を削除)すると どうなるか? • s4: 上記6行目7行目の両方をアンコメントするとど うなるか • 上記4つの場合において bcc32 の場合は -O2 オ プション gcc の場合は -O3 をオプションを付けて コンパイルすると結果はどう変わるか? -O2, -O3 は最適化(optimization) を 施すためのオプションである。 15 確認: a の値はどうなるか? (2/5) • 以下の4通りの場合について確認 array_ex1.c s1 array_ex1.c 6 char a[4]/* = {'a', 'b'}*/; 7 //a[0] = 'c'; array_ex1.c s3 s2 6 char a[4] = {'a', 'b'}; 7 //a[0] = 'c'; array_ex1.c 6 char a[4]/* = {'a', 'b'}*/; 7 a[0] = 'c'; 全部で 4 * 4 = 16 パターン s4 6 char a[4] = {'a', 'b'}; 7 a[0] = 'c'; • 以下の4通りの場合について確認 mintty + bash + GNU C c1 $ gcc array_ex1.c && ./a mintty + bash + GNU C c3 $ gcc -O3 array_ex1.c && ./a cmd + BorlandC++ c2 > bcc32 array_ex1.c && array_ex1 cmd + BorlandC++ c4 > bcc32 -O2 array_ex1.c && array_ex1 16 確認: a の値はどうなるか?(3/5) • 例えばs3s3,s4c3の場合以下のようになる mintty + bash + GNU C $ gcc a[0]: a[1]: a[2]: a[3]: -O3 array_ex1.c && ./a 0x63: 'c' 0xcb: '▒' 0x22: '"' 0x00: '' mintty + bash + GNU C $ gcc a[0]: a[1]: a[2]: a[3]: s3c3 s4c3 -O3 array_ex1.c && ./a 0x63: 'c' 0x62: 'b' 0x00: '' 0x00: '' s3 の状態ではa[1]~a[3] に対し初期 化も代入もされていないので、たまた まこの値になっただけである点に注意。 つまりこの値は未定である。 s4 の状態でも一見 a[2], a[3] に対し 初期化も代入もされていないように 見えるが「初期値式が要素数より少 ない場合、残りは0で初期化」という ルールが適用されるためたため実際 には確実に 0x00 となる事が保証さ れる。 17 確認: a の値はどうなるか?(4/5) • 例えばs3s3,s3c1の場合以下のようになる mintty + bash + GNU C $ gcc a[0]: a[1]: a[2]: a[3]: -O3 array_ex1.c && ./a 0x63: 'c' 0xcb: '▒' 0x22: '"' 0x00: '' mintty + bash + GNU C $ gcc a[0]: a[1]: a[2]: a[3]: s3c3 s3c1 array_ex1.c && ./a 0x63: 'c' 0x00: '' 0x00: '' 0x00: '' ソースコードは同じs1の状態なのにコ ンパイル時のオプションの有無で値が 変わっている点に注意。 このように未定の値は実行してみるま でどうなっているか分からない。 18 確認: a の値はどうなるか?(5/5) s 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 c 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 a[0] 0x63 0x63 0x63 a[1] 0x00 0xcb 0x62 a[2] 0x00 0x20 0x00 a[3] 0x00 0x00 0x00 上記で赤字で示した箇所は本来 未定となる箇所。 つまりたまたまその値になっただ けに過ぎない点に注意。 19 一次元配列の演習 ベクトルの演算 20 演習: ベクトルの演算 • 𝒂, 𝒃 を𝑥, 𝑦, 𝑧の3次元ベクトルとしたときに以下の計 算を行うプログラム作ってみましょう。 • 加算(add)、減算(sub)、 内積(dot product)、外積(cross product) 𝒂 + 𝒃 = 𝑎𝑥 + 𝑏𝑥 , 𝑎𝑦 + 𝑏𝑦 , 𝑎𝑧 + 𝑏𝑧 𝒂 − 𝒃 = 𝑎𝑥 − 𝑏𝑥 , 𝑎𝑦 − 𝑏𝑦 , 𝑎𝑧 − 𝑏𝑧 𝒂 ⋅ 𝒃 = 𝑎𝑥 𝑏𝑥 + 𝑎𝑦 𝑏𝑦 + 𝑎𝑧 𝑏𝑧 𝒂 × 𝒃 = 𝑎𝑦 𝑏𝑧 − 𝑎𝑧 𝑏𝑦 , 𝑎𝑧 𝑏𝑥 − 𝑎𝑥 𝑏𝑧 , 𝑎𝑥 𝑏𝑦 − 𝑎𝑦 𝑏𝑥 21 演習: ベクトルの演算 • 結果は result[0] または result[0~2] に格納しましょう。numresult を適宜設定してく ださい。 • 雛形(vector_xxx_practice_1.c)をダウン ロードして指定された箇所に実装してください。 • ファイル名は、以下の名前にしましょう。 • • • • 加算: 減算: 内積: 外積: vector_add_practice_1.c vector_sub_practice_1.c vector_dot_practice_1.c vector_cross_practice_1.c 22 演習: ベクトルの演算 • 動作テスト用のスクリプト • • • • 加算: 減算: 内積: 外積: vector_add_practice_1_test.sh vector_sub_practice_1_test.sh vector_dot_practice_1_test.sh vector_cross_practice_1_test.sh 23 演習: ベクトルの演算 • ヒント: 書き方はいろいろある。 ループを用いない add ループを用いた add result[0] = a[0] + b[0]; result[1] = a[1] + b[1]; result[2] = a[2] + b[2]; for (i = 0; i < M; i++) { result[i] = a[i] + b[i]; } 24 参考文献 • [1] B.W.カーニハン/D.M.リッチー著 石田晴久 訳、プログラミング言語C 第2版 ANSI 規格準 拠、共立出版(1989)
© Copyright 2024 ExpyDoc