Download : sample-001.c
/* * 2017/11/24 sample-001.c */ /* * メモリモデルの理解 (1) * * 利用方法 * コンパイル * cc -I ~/c/include -c sample-001.c * リンク * cc -o sample-001.exe sample-001.c * 実行 * ./sample-001.exe */ #include <stdio.h> #include "s_memory.h" /* memory モデルを理解するための関数定義 */ /* * main */ int main ( int argc, char *argv[] ) { /* * メモリの操作 ( 情報の記録 : set_memory_value_at ) */ set_memory_value_at ( 100, 1 ); /* 100 番地のセルに 1 を記録する */ set_memory_value_at ( 101, 10 ); /* 101 番地のセルに 10 を記録する */ /* * メモリの操作 ( 情報の参照 : get_memory_value_at ) */ printf ( "100 番地のセルに記録されている数値は %d です。\n", get_memory_value_at ( 100 ) ); printf ( "101 番地のセルに記録されている数値は %d です。\n", get_memory_value_at ( 101 ) ); /* * */ return 0; } /* * */
$ ./sample-001.exe 100 番地のセルに記録されている数値は 1 です。 101 番地のセルに記録されている数値は 10 です。 $
Download : sample-002.c
/* * 2017/11/24 sample-002.c */ /* * メモリモデルの理解 (2) * * 利用方法 * コンパイル * cc -I ~/c/include -c sample-002.c * リンク * cc -o sample-002.exe sample-002.c * 実行 * ./sample-002.exe */ #include <stdio.h> #include "s_memory.h" /* memory モデルを理解するための関数定義 */ /* * print_memory_value * 指定された address の記憶セルの内容を画面に出力する */ void print_memory_value ( int address ) { printf ( "%d 番地のセルに記録されている数値は %d です。\n", address, get_memory_value_at ( address ) /* 値の取出し */ ); } /* * print_memory_set * メモリへの記憶操作を行い、それを報告する */ void print_memory_set ( int address, int value ) { /* 動作の表示 */ printf ( "%d 番地のセルに %d を記録。\n", address, value ); /* address 番地に value を記録する */ set_memory_value_at ( address, value ); /* 値の設定 */ } /* * print_line * 横棒を表示 */ void print_line ( void ) { printf ( "--------------------------------------\n" ); } /* * main */ int main ( int argc, char *argv[] ) { /* * メモリの参照 : 一度記録した情報は何度でも参照できる */ print_memory_set ( 100, 1 ); /* 100 番地のセルに 1 を記録する */ printf ( "一度目 : " ); print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 (一度目) */ printf ( "二度目 : " ); print_memory_value ( 100 ); /* 二度目 */ printf ( "三度目 : " ); print_memory_value ( 100 ); /* 三度目 */ /* * 参照は何度行っても、同じ情報が得られる */ print_line(); /* * 記憶の破壊 : 新しい情報を記録すると以前の記録は失われる */ print_memory_set ( 100, 99 ); /* 100 番地のセルに 99 を記録する */ printf ( "変更後 : " ); print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */ /* * 新しい情報を記憶すると以前の記録された情報は失われる */ /* * 記録は最後のものだけ ( 参照の有無と無関係に最後のものだけを記録 ) */ print_memory_set ( 100, 21 ); /* 100 番地のセルに 21 を記録する */ print_memory_set ( 100, 22 ); /* 100 番地のセルに 22 を記録する */ print_memory_set ( 100, 23 ); /* 100 番地のセルに 23 を記録する */ printf ( "現在値 : " ); print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */ /* * 記録されている情報は最後に記録された物だけ */ /* * */ return 0; } /* * */
$ ./sample-002.exe 100 番地のセルに 1 を記録。 一度目 : 100 番地のセルに記録されている数値は 1 です。 二度目 : 100 番地のセルに記録されている数値は 1 です。 三度目 : 100 番地のセルに記録されている数値は 1 です。 -------------------------------------- 100 番地のセルに 99 を記録。 変更後 : 100 番地のセルに記録されている数値は 99 です。 100 番地のセルに 21 を記録。 100 番地のセルに 22 を記録。 100 番地のセルに 23 を記録。 現在値 : 100 番地のセルに記録されている数値は 23 です。 $
Download : sample-003.c
/* * 2017/11/24 sample-003.c */ /* * メモリモデルの理解 (3) * * 利用方法 * コンパイル * cc -I ~/c/include -c sample-003.c * リンク * cc -o sample-003.exe sample-003.c * 実行 * ./sample-003.exe */ #include <stdio.h> #include "s_memory.h" /* memory モデルを理解するための関数定義 */ /* * print_memory_value * 指定された address の記憶セルの内容を画面に出力する */ void print_memory_value ( int address ) { printf ( "%d 番地のセルに記録されている数値は %d です。\n", address, get_memory_value_at ( address ) /* 値の取出し */ ); } /* * print_memory_set * メモリへの記憶操作を行い、それを報告する */ void print_memory_set ( int address, int value ) { /* 動作の表示 */ printf ( "%d 番地のセルに %d を記録。\n", address, value ); /* address 番地に value を記録する */ set_memory_value_at ( address, value ); /* 値の設定 */ } /* * print_line * 横棒を表示 */ void print_line ( void ) { printf ( "--------------------------------------\n" ); } /* * main */ int main ( int argc, char *argv[] ) { /* * メモリセルの独立性 : 番地の異るセルは独立に振る舞う */ print_memory_set ( 100, 1 ); /* 100 番地のセルに 1 を記録する */ print_memory_set ( 101, 2 ); /* 101 番地のセルに 2 を記録する */ print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */ print_memory_value ( 101 ); /* 101 番地のセルの内容を出力 */ /* * 番地が異れば、記録されている情報も異る */ /* * 記憶の独立性 */ print_memory_set ( 100, 99 ); /* 100 番地のセルに 99 を記録する */ print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */ print_memory_value ( 101 ); /* 101 番地のセルの内容を出力 */ print_line(); /* * 100 番地の情報を書き換えても、101 番地の情報は影響しない */ print_memory_set ( 101, 88 ); /* 101 番地のセルに 88 を記録する */ print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */ print_memory_value ( 101 ); /* 101 番地のセルの内容を出力 */ /* * 逆も真なり */ /* * */ return 0; } /* * */
$ ./sample-003.exe 100 番地のセルに 1 を記録。 101 番地のセルに 2 を記録。 100 番地のセルに記録されている数値は 1 です。 101 番地のセルに記録されている数値は 2 です。 100 番地のセルに 99 を記録。 100 番地のセルに記録されている数値は 99 です。 101 番地のセルに記録されている数値は 2 です。 -------------------------------------- 101 番地のセルに 88 を記録。 100 番地のセルに記録されている数値は 99 です。 101 番地のセルに記録されている数値は 88 です。 $
Download : sample-004.c
/* * 2017/11/24 sample-004.c */ /* * メモリモデルの理解 (4) * * 利用方法 * コンパイル * cc -I ~/c/include -c sample-004.c * リンク * cc -o sample-004.exe sample-004.c * 実行 * ./sample-004.exe */ #include <stdio.h> #include "s_memory.h" /* memory モデルを理解するための関数定義 */ /* * print_memory_value * 指定された address の記憶セルの内容を画面に出力する */ void print_memory_value ( int address ) { printf ( "%d 番地のセルに記録されている数値は %d です。\n", address, get_memory_value_at ( address ) /* 値の取出し */ ); } /* * print_memory_set * メモリへの記憶操作を行い、それを報告する */ void print_memory_set ( int address, int value ) { /* 動作の表示 */ printf ( "%d 番地のセルに %d を記録。\n", address, value ); /* address 番地に value を記録する */ set_memory_value_at ( address, value ); /* 値の設定 */ } /* * print_line * 横棒を表示 */ void print_line ( void ) { printf ( "--------------------------------------\n" ); } /* * main */ int main ( int argc, char *argv[] ) { /* * メモリセルの容量 */ print_memory_set ( 100, 0 ); /* 100 番地のセルに 0 を記録する */ print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */ print_memory_set ( 100, 100 ); /* 100 番地のセルに 100 を記録する */ print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */ print_memory_set ( 100, 255 ); /* 100 番地のセルに 255 を記録する */ print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */ /* * 0 〜 255 ならば、記録できる */ print_line(); /* * メモリセルの容量オーバー */ print_memory_set ( 100, 300 ); /* 100 番地のセルに 300 を記録しようとした */ print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */ /* * 300 は記憶されていない !! * 実は 300 を 256 で割った余り ( 44 ) が記録されている * 256 を越える(オーバーする)情報は捨てられる !! */ /* * */ return 0; } /* * */
$ ./sample-004.exe 100 番地のセルに 0 を記録。 100 番地のセルに記録されている数値は 0 です。 100 番地のセルに 100 を記録。 100 番地のセルに記録されている数値は 100 です。 100 番地のセルに 255 を記録。 100 番地のセルに記録されている数値は 255 です。 -------------------------------------- 100 番地のセルに 300 を記録。 100 番地のセルに記録されている数値は 44 です。 $
Download : sample-005.c
/* * 2017/11/24 sample-005.c */ /* * メモリモデルの理解 (5) * * 利用方法 * コンパイル * cc -I ~/c/include -c sample-005.c * リンク * cc -o sample-005.exe sample-005.c * 実行 * ./sample-005.exe */ #include <stdio.h> #include "s_variable.h" /* memory モデルを理解するための関数定義 */ /* * main */ int main ( int argc, char *argv[] ) { /* * C 言語の変数のメモリモデルによる理解 */ char cvar; /* char 型の変数 cvar の宣言 */ char dvar; /* char 型の変数 dvar の宣言 */ /* * 変数はアドレスをもっている */ printf ( "変数 cvar のアドレスは 16 進数表現で %x です。\n", get_variable_address( cvar ) ); printf ( "変数 dvar のアドレスは 16 進数表現で %x です。\n", get_variable_address( dvar ) ); /* * 変数名が異れば、番地も異っている */ /* * 変数をアドレスを利用して参照 */ cvar = 'c'; /* 変数 cvar に、値 'c' を代入 */ dvar = 'D'; /* 変数 Dvar に、値 'D' を代入 */ printf ( "変数 cvar に記録されている文字は %c です。\n", get_variable_value_at ( get_variable_address( cvar ) ) ); printf ( "変数 dvar に記録されている文字は %c です。\n", get_variable_value_at ( get_variable_address( dvar ) ) ); /* * 変数の値をアドレスを利用して変更 */ set_variable_value_at ( get_variable_address( cvar ), 'X' ); /* 変数 cvar の所に 'X' を記録 */ printf ( "cvar は %c です。\n", cvar ); set_variable_value_at ( get_variable_address( dvar ), 'y' ); /* 変数 dvar の所に 'y' を記録 */ printf ( "dvar は %c です。\n", dvar ); /* * */ return 0; } /* * */
$ ./sample-005.exe 変数 cvar のアドレスは 16 進数表現で 1efe598e です。 変数 dvar のアドレスは 16 進数表現で 1efe598f です。 変数 cvar に記録されている文字は c です。 変数 dvar に記録されている文字は D です。 cvar は X です。 dvar は y です。 $
Download : sample-006.c
/* * 2017/11/24 sample-006.c */ /* * メモリモデルの理解 (6) * * 利用方法 * コンパイル * cc -I ~/c/include -c sample-006.c * リンク * cc -o sample-006.exe sample-006.c * 実行 * ./sample-006.exe */ #include <stdio.h> #include "s_variable.h" /* memory モデルを理解するための関数定義 */ /* * main */ int main ( int argc, char *argv[] ) { /* * C 言語の文字列のメモリモデルによる理解 */ /* * 文字列はアドレスをもっている */ printf ( "文字列 \"abc\" のアドレスは 16 進数表現で %x です。\n", get_string_address( "abc" ) ); /* * 文字列の要素をアドレスを利用して参照 */ printf ( "文字列 \"abc\" の先頭の文字は %c です。\n", get_variable_value_at ( get_string_address( "abc" ) ) ); /* * 文字列の要素の二つ目以後を取り出す */ printf ( "文字列 \"abc\" の先頭の次の文字は %c です。\n", get_variable_value_at ( get_string_address( "abc" ) + 1 ) ); printf ( "文字列 \"abc\" の先頭の次の次の文字は %c です。\n", get_variable_value_at ( get_string_address( "abc" ) + 2 ) ); /* * */ return 0; } /* * */
$ ./sample-006.exe 文字列 "abc" のアドレスは 16 進数表現で 401480 です。 文字列 "abc" の先頭の文字は a です。 文字列 "abc" の先頭の次の文字は b です。 文字列 "abc" の先頭の次の次の文字は c です。 $
Download : sample-007.c
/* * 2017/11/24 sample-007.c */ /* * メモリモデルの理解 (7) * * 利用方法 * コンパイル * cc -I ~/c/include -c sample-007.c * リンク * cc -o sample-007.exe sample-007.c * 実行 * ./sample-007.exe */ #include <stdio.h> #include "s_variable.h" /* memory モデルを理解するための関数定義 */ /* * main */ int main ( int argc, char *argv[] ) { /* * C 言語の変数のメモリモデルによる理解 */ char cvar; /* char 型の変数 cvar の宣言 */ char dvar; /* char 型の変数 dvar の宣言 */ char evar; /* char 型の変数 evar の宣言 */ /* * 変数を並べてて宣言すると (偶然..) アドレスが連続していた.. */ printf ( "変数 cvar のアドレスは 16 進数表現で %x です。\n", get_variable_address( cvar ) ); printf ( "変数 dvar のアドレスは 16 進数表現で %x です。\n", get_variable_address( dvar ) ); printf ( "変数 evar のアドレスは 16 進数表現で %x です。\n", get_variable_address( evar ) ); /* * 変数をアドレスを利用して参照 */ cvar = 'c'; /* 変数 cvar に、値 'c' を代入 */ dvar = 'D'; /* 変数 dvar に、値 'D' を代入 */ evar = '\0'; /* 変数 evar に、値 '\0' を代入 */ printf ( "cvar の所から記録されている文字列は (%s) です。\n", get_variable_address( cvar ) ); /* * アドレス経由で、変数の内容を変更 */ set_variable_value_at ( get_variable_address( cvar ) + 1, 'x' ); /* 変数 cvar のアドレスの次のアドレスは dvar のアドレスなので.. */ printf ( "cvar に記録されている文字は %c です。\n", cvar ); /* 結果的に、dvar の内容が書き変わる */ printf ( "dvar に記録されている文字は %c です。\n", dvar ); /* * */ return 0; } /* * */
$ ./sample-007.exe 変数 cvar のアドレスは 16 進数表現で 5d9978bd です。 変数 dvar のアドレスは 16 進数表現で 5d9978be です。 変数 evar のアドレスは 16 進数表現で 5d9978bf です。 cvar の所から記録されている文字列は (cD) です。 cvar に記録されている文字は c です。 dvar に記録されている文字は x です。 $
Download : sample-008.c
/* * 2017/11/24 sample-008.c */ /* * メモリモデルの理解 (8) * * 利用方法 * コンパイル * cc -I ~/c/include -c sample-008.c * リンク * cc -o sample-008.exe sample-008.c * 実行 * ./sample-008.exe */ #include <stdio.h> #include "s_variable.h" /* memory モデルを理解するための関数定義 */ /* * main */ int main ( int argc, char *argv[] ) { /* * C 言語の変数のメモリモデルによる理解 */ char carray[3]; /* char 型の一次元配列 carray の宣言 (サイズは 3) */ /* 意味的には char carry[0]; -- cvar char carry[1]; -- dvar char carry[2]; -- evar のように考えて良い (cf. sample-007.c) */ /* * 配列の要素のアドレスは連続している事が保証される */ printf ( "変数 carray[0] のアドレスは 16 進数表現で %x です。\n", get_variable_address( carray[0] ) ); printf ( "変数 carray[1] のアドレスは 16 進数表現で %x です。\n", get_variable_address( carray[1] ) ); printf ( "変数 carray[2] のアドレスは 16 進数表現で %x です。\n", get_variable_address( carray[2] ) ); /* * 変数をアドレスを利用して参照 */ carray[0] = 'c'; /* 変数 carray[0] に、値 'c' を代入 */ carray[1] = 'D'; /* 変数 carray[1] に、値 'D' を代入 */ carray[2] = '\0'; /* 変数 carray[2] に、値 '\0' を代入 */ printf ( "carray[0] の所から記録されている文字列は (%s) です。\n", get_variable_address( carray[0] ) ); /* * アドレス経由で、変数の内容を変更 */ set_variable_value_at ( get_variable_address( carray[0] ) + 1, 'x' ); /* 変数 carray[0] のアドレスの次のアドレスは carray[1] のアドレスなので.. */ printf ( "carray[0] に記録されている文字は %c です。\n", carray[0] ); /* 結果的に、carray[1] の内容が書き変わる */ printf ( "carray[1] に記録されている文字は %c です。\n", carray[1] ); /* * */ return 0; } /* * */
$ ./sample-008.exe 変数 carray[0] のアドレスは 16 進数表現で fd95db0 です。 変数 carray[1] のアドレスは 16 進数表現で fd95db1 です。 変数 carray[2] のアドレスは 16 進数表現で fd95db2 です。 carray[0] の所から記録されている文字列は (cD) です。 carray[0] に記録されている文字は c です。 carray[1] に記録されている文字は x です。 $
Download : sample-009.c
/* * 2017/11/24 sample-009.c */ /* * メモリモデルの理解 (9) * * 利用方法 * コンパイル * cc -I ~/c/include -c sample-009.c * リンク * cc -o sample-009.exe sample-009.c * 実行 * ./sample-009.exe */ #include <stdio.h> #include "s_variable.h" /* memory モデルを理解するための関数定義 */ /* * main */ int main ( int argc, char *argv[] ) { /* * */ char carray[3]; /* char 型の一次元配列 carray の宣言 (サイズは 3) */ /* * 配列の要素のアドレスは連続している事が保証される */ carray[0] = 'c'; /* 変数 carray[0] に、値 'c' を代入 */ carray[1] = 'D'; /* 変数 carray[1] に、値 'D' を代入 */ carray[2] = '\0'; /* 変数 carray[2] に、値 '\0' を代入 */ printf ( "carray[0] の所から記録されている文字列は (%s) です。\n", get_variable_address( carray[0] ) ); /* * 配列名は、文字列と同じように扱える */ printf ( "carray が表現している文字列は (%s) です。\n", carray ); /* * 文字列の一部を変更する事ができる */ carray[1] = 'U'; /* ニ文字目を 'U' に変更 */ printf ( "carray が表現している文字列は (%s) です。\n", carray ); carray[0] = 'p'; /* 一字目を 'p' に変更 */ printf ( "carray が表現している文字列は (%s) です。\n", carray ); /* * */ return 0; } /* * */
$ ./sample-009.exe carray[0] の所から記録されている文字列は (cD) です。 carray が表現している文字列は (cD) です。 carray が表現している文字列は (cU) です。 carray が表現している文字列は (pU) です。 $
Download : sample-010.c
/* * 2017/11/24 sample-010.c */ /* * 文字配列と文字列 * * 利用方法 * コンパイル * cc -c sample-010.c * リンク * cc -o sample-010.exe sample-010.c * 実行 * ./sample-010.exe */ #include <stdio.h> /* * main */ int main ( int argc, char *argv[] ) { /* * 文字配列の初期化 */ char carray[3] = "AB"; /* carray[0] = 'A'; carray[1] = 'B'; carray[2] = '\0'; */ printf ( "carray[0] は %c です。\n", carray[0] ); printf ( "carray[1] は %c です。\n", carray[1] ); /* * */ return 0; } /* * */
$ ./sample-010.exe carray[0] は A です。 carray[1] は B です。 $
Download : sample-011.c
/* * 2017/11/24 sample-011.c */ /* * アドレス演算子「&」と間接演算子「*」 * * 利用方法 * コンパイル * cc -c sample-011.c * リンク * cc -o sample-011.exe sample-011.c * 実行 * ./sample-011.exe */ #include <stdio.h> /* * main */ int main ( int argc, char *argv[] ) { /* * アドレス演算子「&」と間接演算子「*」 */ char carray[3] = "AB"; /* * 添字による参照 */ printf ( "carry[0] = %c\n", carry[0] ); printf ( "carry[1] = %c\n", carry[1] ); /* * 間接演算子による参照 */ printf ( "*carry = %c\n", *carry ); printf ( "*(carry+1) = %c\n", *(carry+1) ); /* * address の比較 */ s_print_string ( "&carry[0] = %x\n", &carry[0] ); s_print_string ( "carry = %x\n", carry ); /* * 「&」と「*」は逆演算子 */ s_print_string ( "carry = %x\n", carry ); s_print_string ( "&*carry = %x\n", &*carry ); s_print_string ( "carry[0] = %c\n", carry[0] ); s_print_string ( "*&carry[0] = %c\n", *&carry[0] ); /* * */ return 0; } /* * */
$ ./sample-011.exe carray[0] は A です。 carray[1] は B です。 $
Download : sample-012.c
/* * 2017/11/24 sample-012.c */ /* * 二次元配列とメモリモデル (1) * * 利用方法 * コンパイル * cc -c sample-012.c * リンク * cc -o sample-012.exe sample-012.c * 実行 * ./sample-012.exe */ #include <stdio.h> /* * ◯×ゲームのボード (一次元版) * * y * 0 1 2 (y,t) * +-----+-----+-----+ +-----+ * 0 |(0,0)|(0,1)|(0,2)| |(0,0)| 0 = 0*3+0 = t*3+y * +-----+-----+-----+ +-----+ * t 1 |(1,0)|(1,1)|(1,2)| |(0,1)| 1 = 0*3+1 = t*3+y * +-----+-----+-----+ +-----+ * 2 |(2,0)|(2,1)|(2,2)| |(0,2)| 2 = 0*3+2 = t*3+y * +-----+-----+-----+ +-----+ * |(1,0)| 3 = 1*3+0 = t*3+y * +-----+ * |(1,1)| 4 = 1*3+1 = t*3+y * +-----+ * |(1,2)| 5 = 1*3+2 = t*3+y * +-----+ * |(2,0)| 6 = 2*3+0 = t*3+y * +-----+ * |(2,1)| 7 = 2*3+1 = t*3+y * +-----+ * |(2,2)| 8 = 2*3+2 = x*3+y * +-----+ * */ #define BOARD_SIZE 3 /* ボードのサイズ */ #define SENTE_MARK 'o' /* 先手は 'o' (マル) */ #define GOTE_MARK 'x' /* 後手は 'x' (バツ) */ /* * main */ int main ( int argc, char *argv[] ) { /* * */ char board[BOARD_SIZE*BOARD_SIZE]; /* サイズは 3 × 3 */ int t; /* 縱 */ int y; /* 横 */ /* * ある局面 * * oxx * xoo * oox */ board[0*BOARD_SIZE+0] = 'o'; /* (0,0) */ board[0*BOARD_SIZE+1] = 'x'; /* (0,1) */ board[0*BOARD_SIZE+2] = 'x'; /* (0,2) */ board[1*BOARD_SIZE+0] = 'x'; /* (1,0) */ board[1*BOARD_SIZE+1] = 'o'; /* (1,1) */ board[1*BOARD_SIZE+2] = 'o'; /* (1,2) */ board[2*BOARD_SIZE+0] = 'o'; /* (2,0) */ board[2*BOARD_SIZE+1] = 'x'; /* (2,1) */ board[2*BOARD_SIZE+2] = 'x'; /* (2,2) */ /* * */ t = 0; while ( t < BOARD_SIZE ) { y = 0; while ( y < BOARD_SIZE ) { printf ( "%c", board[t*BOARD_SIZE+y] ); y = y + 1; } printf ( "\n" ); t = t + 1; } /* * */ return 0; } /* * */
$ ./sample-012.exe oxx xoo oxx $
Download : sample-013.c
/* * 2017/11/24 sample-013.c */ /* * 二次元配列とメモリモデル (2) * * 利用方法 * コンパイル * cc -c sample-013.c * リンク * cc -o sample-013.exe sample-013.c * 実行 * ./sample-013.exe */ #include <stdio.h> /* * ◯×ゲームのボード (一次元版) * * y * 0 1 2 (y,t) * +-----+-----+-----+ +-----+ * 0 |(0,0)|(0,1)|(0,2)| |(0,0)| 0 = 0*3+0 = t*3+y * +-----+-----+-----+ +-----+ * t 1 |(1,0)|(1,1)|(1,2)| |(0,1)| 1 = 0*3+1 = t*3+y * +-----+-----+-----+ +-----+ * 2 |(2,0)|(2,1)|(2,2)| |(0,2)| 2 = 0*3+2 = t*3+y * +-----+-----+-----+ +-----+ * |(1,0)| 3 = 1*3+0 = t*3+y * +-----+ * |(1,1)| 4 = 1*3+1 = t*3+y * +-----+ * |(1,2)| 5 = 1*3+2 = t*3+y * +-----+ * |(2,0)| 6 = 2*3+0 = t*3+y * +-----+ * |(2,1)| 7 = 2*3+1 = t*3+y * +-----+ * |(2,2)| 8 = 2*3+2 = x*3+y * +-----+ * */ #define BOARD_SIZE 3 /* ボードのサイズ */ #define SENTE_MARK 'o' /* 先手は 'o' (マル) */ #define GOTE_MARK 'x' /* 後手は 'x' (バツ) */ /* * 二次元の座標を一次元に変換する関数 */ int index2d ( int t, int y ) { return t * BOARD_SIZE + y; } /* * main */ int main ( int argc, char *argv[] ) { /* * */ char board[BOARD_SIZE*BOARD_SIZE]; /* サイズは 3 × 3 */ int t; /* 縱 */ int y; /* 横 */ /* * ある局面 * * oxx * xoo * oox */ board[index2d(0,0)] = 'o'; /* (0,0) */ board[index2d(0,1)] = 'x'; /* (0,1) */ board[index2d(0,2)] = 'x'; /* (0,2) */ board[index2d(1,0)] = 'x'; /* (1,0) */ board[index2d(1,1)] = 'o'; /* (1,1) */ board[index2d(1,2)] = 'o'; /* (1,2) */ board[index2d(2,0)] = 'o'; /* (2,0) */ board[index2d(2,1)] = 'x'; /* (2,1) */ board[index2d(2,2)] = 'x'; /* (2,2) */ /* * */ t = 0; while ( t < BOARD_SIZE ) { y = 0; while ( y < BOARD_SIZE ) { printf ( "%c", board[index2d(t,y)] ); y = y + 1; } printf ( "\n" ); t = t + 1; } /* * */ return 0; } /* * */
$ ./sample-013.exe oxx xoo oxx $
Download : sample-014.c
/* * 2017/11/24 sample-014.c */ /* * 二次元配列とメモリモデル (3) * * 利用方法 * コンパイル * cc -c sample-014.c * リンク * cc -o sample-014.exe sample-014.c * 実行 * ./sample-014.exe */ #include <stdio.h> /* * ◯×ゲームのボード (二次元版) * * y * 0 1 2 * +-----+-----+-----+ * 0 |(0,0)|(0,1)|(0,2)| * +-----+-----+-----+ * t 1 |(1,0)|(1,1)|(1,2)| * +-----+-----+-----+ * 2 |(2,0)|(2,1)|(2,2)| * +-----+-----+-----+ * */ #define BOARD_SIZE 3 /* ボードのサイズ */ #define SENTE_MARK 'o' /* 先手は 'o' (マル) */ #define GOTE_MARK 'x' /* 後手は 'x' (バツ) */ /* * main */ int main ( int argc, char *argv[] ) { /* * */ char board[BOARD_SIZE][BOARD_SIZE]; /* サイズは 3 × 3 */ int t; /* 縱 */ int y; /* 横 */ /* * ある局面 * * oxx * xoo * oox */ board[0][0] = 'o'; /* (0,0) */ board[0][1] = 'x'; /* (0,1) */ board[0][2] = 'x'; /* (0,2) */ board[1][0] = 'x'; /* (1,0) */ board[1][1] = 'o'; /* (1,1) */ board[1][2] = 'o'; /* (1,2) */ board[2][0] = 'o'; /* (2,0) */ board[2][1] = 'x'; /* (2,1) */ board[2][2] = 'x'; /* (2,2) */ /* * */ t = 0; while ( t < BOARD_SIZE ) { y = 0; while ( y < BOARD_SIZE ) { printf ( "%c", board[t][y] ); y = y + 1; } printf ( "\n" ); t = t + 1; } /* * */ return 0; } /* * */
$ ./sample-014.exe oxx xoo oxx $
Download : sample-015.c
/* * 2017/11/24 sample-015.c */ /* * 二次元配列とメモリモデル (3) * * 利用方法 * コンパイル * cc -c sample-015.c * リンク * cc -o sample-015.exe sample-015.c * 実行 * ./sample-015.exe */ #include <stdio.h> /* * ◯×ゲームのボード (一次元版) * * y * 0 1 2 (y,t) * +-----+-----+-----+ +-----+ * 0 |(0,0)|(0,1)|(0,2)| |(0,0)| 0 = 0*3+0 = t*3+y * +-----+-----+-----+ +-----+ * t 1 |(1,0)|(1,1)|(1,2)| |(0,1)| 1 = 0*3+1 = t*3+y * +-----+-----+-----+ +-----+ * 2 |(2,0)|(2,1)|(2,2)| |(0,2)| 2 = 0*3+2 = t*3+y * +-----+-----+-----+ +-----+ * |(1,0)| 3 = 1*3+0 = t*3+y * +-----+ * |(1,1)| 4 = 1*3+1 = t*3+y * +-----+ * |(1,2)| 5 = 1*3+2 = t*3+y * +-----+ * |(2,0)| 6 = 2*3+0 = t*3+y * +-----+ * |(2,1)| 7 = 2*3+1 = t*3+y * +-----+ * |(2,2)| 8 = 2*3+2 = x*3+y * +-----+ * */ #define BOARD_SIZE 3 /* ボードのサイズ */ #define SENTE_MARK 'o' /* 先手は 'o' (マル) */ #define GOTE_MARK 'x' /* 後手は 'x' (バツ) */ /* * main */ int main ( int argc, char *argv[] ) { /* * */ char board[BOARD_SIZE][BOARD_SIZE]; /* サイズは 3 × 3 */ int t; /* 縱 */ int y; /* 横 */ /* * */ printf ( "sizeof ( board[0][0] ) = %d\n", sizeof ( board[0][0] ) ); printf ( "sizeof ( board[0] ) = %d\n", sizeof ( board[0] ) ); printf ( "\n" ); for ( t = 0; t < BOARD_SIZE; t++ ) { printf ( "board[%d]=%x\n", t, &board[t] ); for ( y = 0; y < BOARD_SIZE; y++ ) { /* アドレスの表示 */ printf ( "\t(%d,%d)=%x\n", t, y, &board[t][y] ); } printf ( "\n" ); } /* * */ return 0; } /* * */
$ ./sample-015.exe sizeof ( board[0][0] ) = 1 sizeof ( board[0] ) = 3 board[0]=e46b8d10 (0,0)=e46b8d10 (0,1)=e46b8d11 (0,2)=e46b8d12 board[1]=e46b8d13 (1,0)=e46b8d13 (1,1)=e46b8d14 (1,2)=e46b8d15 board[2]=e46b8d16 (2,0)=e46b8d16 (2,1)=e46b8d17 (2,2)=e46b8d18 $
Download : sample-016.c
/* * 2017/11/24 sample-016.c */ /* * ニ次元配列とメモリモデル (4) * * 利用方法 * コンパイル * cc -c sample-016.c * リンク * cc -o sample-016.exe sample-016.c * 実行 * ./sample-016.exe */ #include <stdio.h> /* * 三次の行列 * * A 列 * 0 1 2 * +-----+-----+-----+ * 0 | a00 | a01 | a02 | * +-----+-----+-----+ * 行 1 | a10 | a11 | a12 | * +-----+-----+-----+ * 2 | a20 | a21 | a22 | * +-----+-----+-----+ * */ #define DIM 3 /* 行列の次元 */ /* * void print_array ( int array[DIM][DIM] ) * array を出力する */ void print_array ( int array[DIM][DIM] ) { int row; /* 行 */ int col; /* 列 */ for ( row = 0; row < DIM; row++ ) { printf ( "%c%c ", " | "[row], "/ \\"[row] ); for ( col = 0; col < DIM; col++ ) { printf ( "%d ", array[row][col] ); } printf ( "%c%c\n", "\\ /"[row], " | "[row] ); } } /* * void add_array ( int c[DIM][DIM], int a[DIM][DIM], int b[DIM][DIM] ) * c = a + b */ void add_array ( int c[DIM][DIM], int a[DIM][DIM], int b[DIM][DIM] ) { int row; /* 行 */ int col; /* 列 */ for ( row = 0; row < DIM; row++ ) { for ( col = 0; col < DIM; col++ ) { c[row][col] = a[row][col] + b[row][col]; } } } /* * main */ int main ( int argc, char *argv[] ) { /* * */ int a[DIM][DIM] = { {1, 2, 3}, {2, 3, 4}, {3, 4, 5} }; /* 配列の初期化 */ int b[DIM][DIM] = { {1, 1, 1}, {3, 2, 1}, {4, 2, 0} }; int c[DIM][DIM]; /* a + b の結果を入れる行列 */ /* * */ printf ( "行列 a\n" ); print_array ( a ); printf ( "と、\n" ); printf ( "行列 b\n" ); print_array ( b ); printf ( "の和は\n" ); add_array ( c, a, b ); /* c = a + b */ print_array ( c ); printf ( "になります。\n" ); /* * */ return 0; } /* * */
$ ./sample-016.exe 行列 a / 1 2 3 \ | 2 3 4 | \ 3 4 5 / と、 行列 b / 1 1 1 \ | 3 2 1 | \ 4 2 0 / の和は / 2 3 4 \ | 5 5 5 | \ 7 6 5 / になります。 $
Download : sample-017-01.c
/* * 2017/11/17 sample-017-01.c */ #include <stdio.h> /* * 利用方法 * コンパイル * cc -c sample-017-01.c */ typedef struct { unsigned char intAry[ sizeof ( int ) ]; } Int; void print_int_as_char_list ( Int ia ) { int i; for ( i = 0; i < sizeof ( int ); i++ ) { printf ( "%d ", ia.intAry[i] ); } printf ( "\n" ); }
Download : sample-017.c
/* * 2017/11/24 sample-017.c */ /* * 二次元配列とメモリモデル (5) * * 利用方法 * コンパイル * cc -c sample-017.c * リンク * cc -o sample-017.exe sample-017.c * 実行 * ./sample-017.exe */ #include <stdio.h> #if 0 /* * 利用方法 * コンパイル * cc -I ~/c/include -c sample-017.c * cc -I ~/c/include -c sample-017-01.c * cc -o sample-017.exe sample-017.o sample-017-01.o * 実行 * ./sample-017.exe */ #endif /* * 整数とメモリモデル * * +---+---+---+---+ +---+ * int | | == char | | * +---+---+---+---+ +---+ * | | * +---+ * | | * +---+ * | | * +---+ * * */ int make_int ( int b1, int b2, int b3, int b4 ) { return b1 + 256 * ( b2 + 256 * ( b3 + 256 * b4 ) ); } /* * main */ int main ( int argc, char *argv[] ) { /* * */ int i; printf ( "sizeof( int ) = %d\n", sizeof ( int ) ); i = make_int ( 1, 0, 0, 0 ); printf ( "i = make_int ( 1, 0, 0, 0 ) = %d\n", i ); print_int_as_char_list ( i ); i = make_int ( 2, 3, 0, 0 ); printf ( "i = make_int ( 2, 3, 0, 0 ) = %d\n", i ); print_int_as_char_list ( i ); i = make_int ( 3, 4, 5, 0 ); printf ( "i = make_int ( 3, 4, 5, 0 ) = %d\n", i ); print_int_as_char_list ( i ); i = make_int ( 4, 5, 6, 7 ); printf ( "i = make_int ( 4, 5, 6, 7 ) = %d\n", i ); print_int_as_char_list ( i ); /* * */ printf ( "----\n" ); /* * */ i = 255; printf ( "i = %d\n", i ); print_int_as_char_list ( i ); i = 256; printf ( "i = %d\n", i ); print_int_as_char_list ( i ); /* * */ return 0; } /* * */
$ ./sample-017.exe sizeof( int ) = 4 i = make_int ( 1, 0, 0, 0 ) = 1 1 0 0 0 i = make_int ( 2, 3, 0, 0 ) = 770 2 3 0 0 i = make_int ( 3, 4, 5, 0 ) = 328707 3 4 5 0 i = make_int ( 4, 5, 6, 7 ) = 117835012 4 5 6 7 ---- i = 255 255 0 0 0 i = 256 0 1 0 0 $
Download : sample-018.c
/* * 2017/11/24 sample-018.c */ /* * 再帰呼出しとメモリモデル (1) * * 利用方法 * コンパイル * cc -c sample-018.c * リンク * cc -o sample-018.exe sample-018.c * 実行 * ./sample-018.exe */ #include <stdio.h> /* * 再帰を利用した階乗の計算(既出) * * 1 ( n < 1 ) * n! = { * n * { (n-1)! } */ int fact ( int n ) { if ( n < 1 ) { // n が 0 の時 return 1; } else { return fact ( n - 1 ) * n; // 再帰を利用して計算 } } int main ( void ) { /* * */ int n = 5; /* * */ printf ( "fact(%d)=%d\n", n, fact(n) ); /* * */ return 0; } /* * */
$ ./sample-018.exe fact(5)=120 $
Download : sample-019.c
/* * 2017/11/24 sample-019.c */ /* * 再帰呼出しとメモリモデル (2) * * 利用方法 * コンパイル * cc -c sample-019.c * リンク * cc -o sample-019.exe sample-019.c * 実行 * ./sample-019.exe */ #include <stdio.h> /* * 仮引数変数 n のアドレスと値はどうなっているか ? */ int fact ( int n ) { int f; printf ( "(fact:前) n = %d, &n = %x\n", n, &n ); if ( n < 1 ) { f = 1; } else { f = fact ( n - 1 ) * n; } printf ( "(fact:後) n = %d, &n = %x\n", n, &n ); return f; } int main ( void ) { /* * */ int n = 5; int f; /* * */ printf ( "(main) n = %d, &n = %x\n", n, &n ); /* * */ f = fact(n); printf ( "fact(%d)=%d\n", n, f ); /* * */ return 0; } /* * */
$ ./sample-019.exe (main) n = 5, &n = 18de2078 (fact:前) n = 5, &n = 18de204c (fact:前) n = 4, &n = 18de201c (fact:前) n = 3, &n = 18de1fec (fact:前) n = 2, &n = 18de1fbc (fact:前) n = 1, &n = 18de1f8c (fact:前) n = 0, &n = 18de1f5c (fact:後) n = 0, &n = 18de1f5c (fact:後) n = 1, &n = 18de1f8c (fact:後) n = 2, &n = 18de1fbc (fact:後) n = 3, &n = 18de1fec (fact:後) n = 4, &n = 18de201c (fact:後) n = 5, &n = 18de204c fact(5)=120 $
Download : sample-020.c
/* * 2017/11/24 sample-020.c */ /* * 関数呼出しとメモリモデル (1) * * 利用方法 * コンパイル * cc -c sample-020.c * リンク * cc -o sample-020.exe sample-020.c * 実行 * ./sample-020.exe */ #include <stdio.h> /* * 利用方法 * コンパイル * cc -o sample-020.exe sample-020.c * 実行 * ./sample-020.exe */ /* * 引数のアドレスは ? ( 引数の順に並んいる ) */ int subfunc ( int a, int b ) { printf ( "a = %d, &a = %x\n", a, &a ); printf ( "b = %d, &b = %x\n", b, &b ); } int main ( void ) { /* * */ subfunc ( 2, 4 ); /* * */ return 0; } /* * */
$ ./sample-020.exe a = 2, &a = afaacc1c b = 4, &b = afaacc18 $
Download : sample-021.c
/* * 2017/11/24 sample-021.c */ /* * 関数呼出しとメモリモデル (2) * * 利用方法 * コンパイル * cc -c sample-021.c * リンク * cc -o sample-021.exe sample-021.c * 実行 * ./sample-021.exe */ #include <stdio.h> /* * 一つの引数変数から(ポインター経由で..)他の引数変数を参照する事ができる */ int subfunc ( int a, int b ) { printf ( "a = %d, &a = %x\n", a, &a ); printf ( "b = %d, &b = %x\n", b, &b ); /* * 変数 b を利用して変数 a の値が参照できる */ printf ( "*(&b-1) = %d, &b-1 = %x\n", *(&b-1), &b-1 ); /* * 変数 b を利用して変数 a の値を変更(代入)できる */ *(&b-1) = 10; printf ( "a = %d\n", a ); } int main ( void ) { /* * */ subfunc ( 2, 4 ); /* * */ return 0; } /* * */
$ ./sample-021.exe a = 2, &a = 41706cec b = 4, &b = 41706ce8 *(&b-1) = 0, &b-1 = 41706ce4 a = 2 $
Download : sample-022.c
/* * 2017/11/24 sample-022.c */ /* * 関数呼出しとメモリモデル (3) * * 利用方法 * コンパイル * cc -c sample-022.c * リンク * cc -o sample-022.exe sample-022.c * 実行 * ./sample-022.exe */ #include <stdio.h> /* * 先頭の引数のポインタを利用して、残りの引数を参照する */ int subfunc ( int a, ... ) { printf ( "a = %d, &a = %x\n", a, &a ); printf ( "*(&a+1) = %d, &a + 1 = %x\n", *(&a+1), &a+1 ); printf ( "*(&a+2) = %d, &a + 2 = %x\n", *(&a+2), &a+2 ); } int main ( void ) { /* * */ subfunc ( 1,2,3,4,5 ); /* * */ return 0; } /* * */
$ ./sample-022.exe a = 1, &a = c9d9fbdc *(&a+1) = -2023167072, &a + 1 = c9d9fbe0 *(&a+2) = 11116, &a + 2 = c9d9fbe4 $
Download : sample-023.c
/* * 2017/11/17 sample-023.c */ #include <stdio.h> /* * 利用方法 * コンパイル * cc -o sample-023.exe sample-023.c * 実行 * ./sample-023.exe */ /* * 引数をアドレス経由で参照する * 最初の引数 n は、他の引数の個数としての情報を担う * 関数(のプログラム作成時)側では、 * (実行時の呼出の時に)幾つの引数が指定されるかを知る術がない * 最初の引数 n の「値」を信じて振る舞うしかない */ int subfunc ( int n, ... ) { int i; for ( i = 0; i < n; i++ ) { printf ( "arg[%d]=%d\n", i, *(&n+1+i) ); } } int main ( void ) { /* * */ printf ( "subfunc ( 5,1,2,3,4,5 );\n" ); subfunc ( 5,1,2,3,4,5 ); // 1 から 5 の追加の引数の個数を適切に指定 printf ( "subfunc ( 3,9,8,7,6 );\n" ); subfunc ( 3,9,8,7,6 ); // 4 つの追加の引数があるのに 3 としているので、最後の値は利用されない /* * */ return 0; } /* * */
$ ./sample-023.exe subfunc ( 5,1,2,3,4,5 ); arg[0]=0 arg[1]=0 arg[2]=0 arg[3]=3 arg[4]=-1140358144 subfunc ( 3,9,8,7,6 ); arg[0]=0 arg[1]=0 arg[2]=0 $
Download : sample-024.c
/* * 2017/11/17 sample-024.c */ #include <stdio.h> #include "s_print.h" /* * 利用方法 * コンパイル * cc -I ~/c/include -o sample-024.exe sample-024.c * 実行 * ./sample-024.exe */ /* * 最初の引数に指定した文字列の中に 「%」があったら、後の引数の値に置き換える */ int print_int_with_format ( char *fmt, int a, ... ) { int i; int j; j = 0; i = 0; while ( fmt[i] != '\0' ) { /* 文字列の終わりがくるまで */ if ( fmt[i] == '%' ) { /* '%' がきたら特別処理 printf ( "%d", *(&a+j) ); /* 追加引数の値を取り出し出力 */ j = j + 1; /* 次の引数の準備 */ } else { /* '%' 以外は.. */ s_print_char ( fmt[i] ); /* その文字をそのまま出力 */ } i = i + 1; /* 次の文字 */ } } int main ( void ) { /* * */ print_int_with_format ( "%\n", 99 ); print_int_with_format ( "i = %, j = %\n", 10, 20 ); print_int_with_format ( "1 st = %, 2nd = %, 3rd = % \n", 10, 20, 90 ); /* * */ return 0; } /* * */
$ ./sample-024.exe i = , j = 1 st = , 2nd = , 3rd = $
Download : sample-025.c
/* * 2017/11/24 sample-025.c */ /* * printf とメモリモデル (1) * * 利用方法 * コンパイル * cc -I ~/c/include -c sample-025.c * リンク * cc -o sample-025.exe sample-025.c * 実行 * ./sample-025.exe */ #include <stdio.h> #include "s_print.h" /* * main */ int main ( int argc, char *argv[] ) { /* * */ // printf ( "..." ); /* これまで printf は「文字列出力」専門だった */ /* 実は、もっと、凄い機能がある */ printf ( "%d\n", 99 ); // 文字列の中に「%d」をいれると、これは、その後の引数の // 整数値引数の値に書き変わる /* * 引数の個数は可変長 */ printf ( "i=%d, j=%d, k=%d\n", 10, 20, 90 ); /* * 上と同じ事をする命令列 ( いままでは面倒な事をしていた ) */ s_print_string ( "i=" ); s_print_int ( 10 ); s_print_string ( ", j=" ); s_print_int ( 20 ); s_print_string ( ", k=" ); s_print_int ( 90 ); s_print_newline(); /* * */ return 0; } /* * */
$ ./sample-025.exe 99 i=10, j=20, k=90 i=10, j=20, k=90 $
Download : sample-026.c
/* * 2017/11/24 sample-026.c */ /* * printf とメモリモデル (2) * * 利用方法 * コンパイル * cc -I ~/c/include -c sample-026.c * リンク * cc -o sample-026.exe sample-026.c * 実行 * ./sample-026.exe */ #include <stdio.h> #include "s_print.h" /* * printf を利用してみる */ int main ( void ) { /* * */ printf ( "abc\n" ); /* いままでと同じ */ /* 文字列がそのままでる */ printf ( "i=%d\n", 10 ); /* 文字列の中の 「%d」の部分が、二つ目の引数 10 に変る */ printf ( "i=%d, j=%d\n", 10, 20 ); /* 「%d」が二度でれば二度めは三つ目の引数の値を利用 */ printf ( "a=%f\n", 12.34 ); /* 実数(浮動小数点数) の場合は 「%f」を使う */ printf ( "i=%d, a=%f, c=%c, s=%s\n", 123, 12.34, 'a', "abc" ); /* 混在も可能 %c が文字 %s が文字列(文字型へのポインタ値) */ /* * */ return 0; } /* * */
$ ./sample-026.exe abc i=10 i=10, j=20 a=12.340000 i=123, a=12.340000, c=a, s=abc $
Download : sample-027.c
/* * 2017/11/24 sample-027.c */ /* * printf とメモリモデル (3) * * 利用方法 * コンパイル * cc -I ~/c/include -c sample-027.c * リンク * cc -o sample-027.exe sample-027.c * 実行 * ./sample-027.exe */ #include <stdio.h> #include "s_print.h" /* * printf の更なる機能 : 書式付きの出力 */ int main ( void ) { /* * 同じ数値を異る形式(書式 / format)で出力できる */ printf ( "a=%10.6f\n", -12.34 ); /* 出力する形式を指定できる 10.6 は、全体 10 桁、小数点以下 6 桁の意味 */ printf ( "a=%20.10f\n", -12.34 ); /* 出力する形式を指定できる 20.10 は、全体 20 桁、小数点以下 10 桁の意味 */ /* * */ return 0; } /* * */
$ ./sample-027.exe a=-12.340000 a= -12.3400000000 $
Download : sample-028.c
/* * 2017/11/24 sample-028.c */ /* * printf とメモリモデル (4) * * 利用方法 * コンパイル * cc -c sample-028.c * リンク * cc -o sample-028.exe sample-028.c * 実行 * ./sample-028.exe */ #include <stdio.h> /* * scanf, printf (出力関数) の入力版 */ int main ( void ) { /* * */ int i; /* * */ printf ( "i の値を入力してください " ); scanf ( "%d", &i ); /* '%d' --> printf と同じ */ /* i = s_input_int(); */ /* i = 99; の時 scanf ( "%d", i ); は、 scanf ( "%d", 99 ); の意味。 これでは、scanf はどうやっても i の値を得る事ができない。 そこで、「&i」を指定 ( i のポインタ値がわかれば、 i の値が変更できる ) */ /* * */ printf ( "入力された i の値は %d でした\n", i ); /* * */ return 0; } /* * */
10
$ ./sample-028.exe < sample-028.in i の値を入力してください 10 入力された i の値は 10 でした $
/* * 課題 20171124-01 * * 2017/11/24 20171124-01-QQQQ.c * * メモリ操作での和 * s_memory.h を利用し、 * 100 番地の内容と 101 番地の内容の和を * 102 番地に入れるプログラムを作成しなさい */ /* * 利用方法 * コンパイル * cc -I ~/c/include -o BASENAME.exe 20171124-01-QQQQ.c * 実行 * ./BASENAME.exe */ #include <stdio.h> #include "s_memory.h" /* * print_memory_value * 指定された address の記憶セルの内容を画面に出力する */ void print_memory_value ( int address ) { printf ( "%d 番地のセルに記録されている数値は %d です。\n", address, get_memory_value_at ( address ) /* 値の取出し */ ); } /* * */ int main ( int argc, char *argv[] ) { /* 値の設定 */ /* * メモリセルの容量 */ set_memory_value_at ( 100, 12 ); /* 100 番地のセルに 12 を記録する */ set_memory_value_at ( 101, 78 ); /* 100 番地のセルに 78 を記録する */ /* * 100 番地の値と 101 番地の値の和を 102 番地にいれる * -> 102 番地に 12 + 78 = 100 をいれる */ /* set_memory_value_at ( 102, 100 ); でも間違えではない */ /* 一応、100 番地と 101 番地の値を取り出して、 その和を計算して、102 番地に設定する */ set_memory_value_at ( 102, get_memory_value_at ( 100 ) + get_memory_value_at ( 101 ) ); /* char cvar = 12; char dvar = 78 char evar; evar = cvar + dver; /* * 結果の出力 */ print_memory_value ( 102 ); /* 102 番地のセルの内容を出力 */ return 0; } /* * */
/* * 課題 20171124-02 * * 2017/11/24 20171124-02-QQQQ.c * * アドレスを利用した間接参照 * 代入文を利用せず、s_variable.h を利用して、 * 変数 cvar の値を 1 だけふやせ */ #include <stdio.h> #include "s_variable.h" /* memory モデルを理解するための関数定義 */ /* * 利用方法 * コンパイル * cc -I ~/c/include -o BASENAME.exe 20171124-02-QQQQ.c * 実行 * ./BASENAME.exe */ int main ( void ) { /* * C 言語の変数のメモリモデルによる理解 */ char cvar = 'p'; /* char 型の変数 cvar の宣言 */ printf ( "cvar は %c です。\n", cvar ); /* cvar <- 'q' = 'p' + 1 = cvar + 1 cvar の値を変更したい 「代入文を使わない」 アドレスを利用する cf sample-005.c */ set_variable_value_at ( get_variable_address( cvar ), /* cvar のアドレス */ get_variable_value_at ( get_variable_address( cvar ) ) /* cvar のアドレスをとって、 そのアドレスを利用して、cvar の値を取り出す */ /* 単に「cvar」としてもよいが... */ + 1 ); printf ( "cvar は %c になりました。\n", cvar ); /* * */ return 0; } /* * */
#include <stdio.h> void change_value_function ( char ca[1] ) { /* 引数に配列名を指定すると、その要素が関数内で参照(値の変更も..)できる 指定した文字型配列の先頭の要素の値を 'B' に書き換える */ ca[0] = 'B'; /* 配列の要素の値を変更している */ }; int main(int argc, char *argv[]) { char cvar[1] = { 'A' }; /* 関数を呼んで、その中で、変数 cver[0] の値を、 'B' に変更したい */ printf ( "関数呼び出しの前 : cvar[0] = '%c'\n", cvar[0] ); change_value_function ( cvar ); /* 配列名を指定している */ printf ( "関数呼び出しの後 : cvar[0] = '%c'\n", cvar[0] ); return 0; }
#include <stdio.h> void change_value_function ( char *ca ) { /* アドレス値をもつ変数の宣言は、型+「*」で宣言する char *ca <-> (*ca) -> char 型変数 */ /* 引数に配列名を指定すると、その要素が関数内で参照(値の変更も..)できる 指定した文字型配列の先頭の要素の値を 'B' に書き換える */ *ca = 'B'; /* 配列の要素の値を変更している */ /* 「*」を利用して、アドレス経由で、値の変更をおこなっている */ }; int main(int argc, char *argv[]) { char cvar = 'A'; /* 関数を呼んで、その中で、変数 cver の値を、 'B' に変更したい */ printf ( "関数呼び出しの前 : cvar = '%c'\n", cvar ); change_value_function ( &cvar ); /* 変数のアドレスを指定している */ /* & を利用する事により、scanf の真似事ができる */ printf ( "関数呼び出しの後 : cvar = '%c'\n", cvar ); return 0; }
/* * 2017/11/24 sample-001.c */ /* * メモリモデルの理解 (1) * * 利用方法 * コンパイル * cc -I ~/c/include -c sample-001.c * リンク * cc -o sample-001.exe sample-001.c * 実行 * ./sample-001.exe */ #include <stdio.h> #include "s_memory.h" /* memory モデルを理解するための関数定義 */ /* * main */ int main ( int argc, char *argv[] ) { /* * メモリの操作 ( 情報の記録 : set_memory_value_at ) * set_memory_value_at ( address, value ); * メモリの address 番地に value を記録する * address : 0 ? 1000 位まで * value : 0 ? 255 の 1 byte の整数値 */ /*[最初] +-------+ 0 | ?? | +-------+ 1 | ?? | +-------+ | | ... | | +-------+ 100 | ?? | +-------+ 101 | ?? | +-------+ | | | | ... | | */ set_memory_value_at ( 100, 1 ); /* 100 番地のセルに 1 を記録する */ set_memory_value_at ( 101, 10 ); /* 101 番地のセルに 10 を記録する */ /*[最初] +-------+ 0 | ?? | +-------+ 1 | ?? | +-------+ | | ... | | +-------+ 100 | 1 | ?? -> 1 +-------+ 101 | 10 | ?? -> 10 +-------+ | | | | ... | | */ /* * メモリの操作 ( 情報の参照 : get_memory_value_at ) * get_memory_value_at ( address ) * 返り値として、address の場所のセルの値 ( 1 byte ) が得られる */ printf ( "100 番地のセルに記録されている数値は %d です。\n", get_memory_value_at ( 100 ) ); /* 「1」が表示される */ printf ( "101 番地のセルに記録されている数値は %d です。\n", get_memory_value_at ( 101 ) ); /* 「10」が表示される */ /* * */ return 0; } /* * */
/* * 2017/11/24 sample-002.c */ /* * メモリモデルの理解 (2) * * 利用方法 * コンパイル * cc -I ~/c/include -c sample-002.c * リンク * cc -o sample-002.exe sample-002.c * 実行 * ./sample-002.exe */ #include <stdio.h> #include "s_memory.h" /* memory モデルを理解するための関数定義 */ /* * print_memory_value * 指定された address の記憶セルの内容を画面に出力する */ void print_memory_value ( int address ) { printf ( "%d 番地のセルに記録されている数値は %d です。\n", address, get_memory_value_at ( address ) /* 値の取出し */ ); } /* * print_memory_set * メモリへの記憶操作を行い、それを報告する */ void print_memory_set ( int address, int value ) { /* 動作の表示 */ printf ( "%d 番地のセルに %d を記録。\n", address, value ); /* address 番地に value を記録する */ set_memory_value_at ( address, value ); /* 値の設定 */ } /* * print_line * 横棒を表示 */ void print_line ( void ) { printf ( "--------------------------------------\n" ); } /* * main */ int main ( int argc, char *argv[] ) { /* * メモリの参照 : 一度記録した情報は何度でも参照できる * これも、変数の性質として前に学んだ内容 */ print_memory_set ( 100, 1 ); /* 100 番地のセルに 1 を記録する */ printf ( "一度目 : " ); print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 (一度目) */ printf ( "二度目 : " ); print_memory_value ( 100 ); /* 二度目 */ printf ( "三度目 : " ); print_memory_value ( 100 ); /* 三度目 */ /* * 参照は何度行っても、同じ情報が得られる */ print_line(); /* * 記憶の破壊 : 新しい情報を記録すると以前の記録は失われる */ print_memory_set ( 100, 99 ); /* 100 番地のセルに 99 を記録する */ printf ( "変更後 : " ); print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */ /* * 新しい情報を記憶すると以前の記録された情報は失われる */ /* * 記録は最後のものだけ ( 参照の有無と無関係に最後のものだけを記録 ) */ print_memory_set ( 100, 21 ); /* 100 番地のセルに 21 を記録する */ print_memory_set ( 100, 22 ); /* 100 番地のセルに 22 を記録する */ print_memory_set ( 100, 23 ); /* 100 番地のセルに 23 を記録する */ printf ( "現在値 : " ); print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */ /* * 記録されている情報は最後に記録された物だけ */ /* * */ return 0; } /* * */
/* * 2017/11/24 sample-003.c */ /* * メモリモデルの理解 (3) * * 利用方法 * コンパイル * cc -I ~/c/include -c sample-003.c * リンク * cc -o sample-003.exe sample-003.c * 実行 * ./sample-003.exe */ #include <stdio.h> #include "s_memory.h" /* memory モデルを理解するための関数定義 */ /* * print_memory_value * 指定された address の記憶セルの内容を画面に出力する */ void print_memory_value ( int address ) { printf ( "%d 番地のセルに記録されている数値は %d です。\n", address, get_memory_value_at ( address ) /* 値の取出し */ ); } /* * print_memory_set * メモリへの記憶操作を行い、それを報告する */ void print_memory_set ( int address, int value ) { /* 動作の表示 */ printf ( "%d 番地のセルに %d を記録。\n", address, value ); /* address 番地に value を記録する */ set_memory_value_at ( address, value ); /* 値の設定 */ } /* * print_line * 横棒を表示 */ void print_line ( void ) { printf ( "--------------------------------------\n" ); } /* * main */ int main ( int argc, char *argv[] ) { /* * メモリセルの独立性 : 番地の異るセルは独立に振る舞う */ print_memory_set ( 100, 1 ); /* 100 番地のセルに 1 を記録する */ print_memory_set ( 101, 2 ); /* 101 番地のセルに 2 を記録する */ print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */ print_memory_value ( 101 ); /* 101 番地のセルの内容を出力 */ /* * 番地が異れば、記録されている情報も異る */ /* * 記憶の独立性 */ print_memory_set ( 100, 99 ); /* 100 番地のセルに 99 を記録する */ print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */ print_memory_value ( 101 ); /* 101 番地のセルの内容を出力 */ print_line(); /* * 100 番地の情報を書き換えても、101 番地の情報は影響しない */ print_memory_set ( 101, 88 ); /* 101 番地のセルに 88 を記録する */ print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */ print_memory_value ( 101 ); /* 101 番地のセルの内容を出力 */ /* * 逆も真なり */ /* * */ return 0; } /* * */
/* * 2017/11/24 sample-004.c */ /* * メモリモデルの理解 (4) * * 利用方法 * コンパイル * cc -I ~/c/include -c sample-004.c * リンク * cc -o sample-004.exe sample-004.c * 実行 * ./sample-004.exe */ #include <stdio.h> #include "s_memory.h" /* memory モデルを理解するための関数定義 */ /* * print_memory_value * 指定された address の記憶セルの内容を画面に出力する */ void print_memory_value ( int address ) { printf ( "%d 番地のセルに記録されている数値は %d です。\n", address, get_memory_value_at ( address ) /* 値の取出し */ ); } /* * print_memory_set * メモリへの記憶操作を行い、それを報告する */ void print_memory_set ( int address, int value ) { /* 動作の表示 */ printf ( "%d 番地のセルに %d を記録。\n", address, value ); /* address 番地に value を記録する */ set_memory_value_at ( address, value ); /* 値の設定 */ } /* * print_line * 横棒を表示 */ void print_line ( void ) { printf ( "--------------------------------------\n" ); } /* * main */ int main ( int argc, char *argv[] ) { /* * メモリセルの容量(記憶できるサイズ) * 1 byte = 8 bit = 0 ? 255 ( = 2^8 - 1 ) の 256 通りの数 * もし、容量を超える値を記録させようとすると.. ? * 「オーバーフロー」する */ print_memory_set ( 100, 0 ); /* 100 番地のセルに 0 を記録する */ print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */ print_memory_set ( 100, 100 ); /* 100 番地のセルに 100 を記録する */ print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */ print_memory_set ( 100, 255 ); /* 100 番地のセルに 255 を記録する */ print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */ /* * 0 〜 255 ならば、記録できる */ print_line(); /* * メモリセルの容量オーバー */ print_memory_set ( 100, 300 ); /* 100 番地のセルに 300 を記録しようとした */ print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */ /* * 300 は記憶されていない !! * 実は 300 を 256 で割った余り ( 44 ) が記録されている * 256 を越える(オーバーする)情報は捨てられる !! */ /* * */ return 0; } /* * */
/* * 2017/11/24 sample-005.c */ /* * メモリモデルの理解 (5) * * 利用方法 * コンパイル * cc -I ~/c/include -c sample-005.c * リンク * cc -o sample-005.exe sample-005.c * 実行 * ./sample-005.exe */ #include <stdio.h> #include "s_variable.h" /* memory モデルを理解するための関数定義 */ /* * main */ int main ( int argc, char *argv[] ) { /* * C 言語の変数のメモリモデルによる理解 */ char cvar; /* char 型の変数 cvar の宣言 */ /* sizeof ( char ) = 1 なので、 1 個のセルに対応 */ /* セルには番地が対応してる */ char dvar; /* char 型の変数 dvar の宣言 */ /* * 変数はアドレスをもっている */ printf ( "変数 cvar のアドレスは 16 進数表現で %x です。\n", get_variable_address( cvar ) /* その変数に対応した、(連続したセルの先頭の)セルのアドレス(番地) */ ); printf ( "変数 dvar のアドレスは 16 進数表現で %x です。\n", get_variable_address( dvar ) ); /* * 変数名が異れば、番地も異っている */ /* * 変数をアドレスを利用して参照 */ cvar = 'c'; /* 変数 cvar に、値 'c' を代入 */ dvar = 'D'; /* 変数 Dvar に、値 'D' を代入 */ /* 代入 : その変数に対応したセルの情報を書き換えている */ printf ( "変数 cvar に記録されている文字は %c です。\n", get_variable_value_at ( get_variable_address( cvar ) ) /* アドレスが解れば、その値が取り出せる */ /* その値は、変数の値そのもの */ /* -> メモリのセルの性質 */ ); printf ( "変数 dvar に記録されている文字は %c です。\n", get_variable_value_at ( get_variable_address( dvar ) ) ); /* * 変数の値をアドレスを利用して変更 */ set_variable_value_at ( get_variable_address( cvar ), 'X' ); /* 変数 cvar の所に 'X' を記録 */ /* アドレスが解れば、セルの情報(変数の情報)も書き換えられる */ printf ( "cvar は %c です。\n", cvar ); set_variable_value_at ( get_variable_address( dvar ), 'y' ); /* 変数 dvar の所に 'y' を記録 */ printf ( "dvar は %c です。\n", dvar ); /* * */ return 0; } /* * */
/* * 2017/11/24 sample-006.c */ /* * メモリモデルの理解 (6) * * 利用方法 * コンパイル * cc -I ~/c/include -c sample-006.c * リンク * cc -o sample-006.exe sample-006.c * 実行 * ./sample-006.exe */ #include <stdio.h> #include "s_variable.h" /* memory モデルを理解するための関数定義 */ /* * main */ int main ( int argc, char *argv[] ) { /* * C 言語の文字列のメモリモデルによる理解 */ /* * 文字列はアドレスをもっている */ printf ( "文字列 \"abc\" のアドレスは 16 進数表現で %x です。\n", get_string_address( "abc" ) ); /* * 文字列の要素をアドレスを利用して参照 */ printf ( "文字列 \"abc\" の先頭の文字は %c です。\n", get_variable_value_at ( get_string_address( "abc" ) ) ); /* * 文字列の要素の二つ目以後を取り出す */ printf ( "文字列 \"abc\" の先頭の次の文字は %c です。\n", get_variable_value_at ( get_string_address( "abc" ) + 1 ) ); printf ( "文字列 \"abc\" の先頭の次の次の文字は %c です。\n", get_variable_value_at ( get_string_address( "abc" ) + 2 ) ); /* * */ return 0; } /* * */
/* * 2017/11/24 sample-007.c */ /* * メモリモデルの理解 (7) * * 利用方法 * コンパイル * cc -I ~/c/include -c sample-007.c * リンク * cc -o sample-007.exe sample-007.c * 実行 * ./sample-007.exe */ #include <stdio.h> #include "s_variable.h" /* memory モデルを理解するための関数定義 */ /* * main */ int main ( int argc, char *argv[] ) { /* * C 言語の変数のメモリモデルによる理解 */ char cvar; /* char 型の変数 cvar の宣言 */ char dvar; /* char 型の変数 dvar の宣言 */ char evar; /* char 型の変数 evar の宣言 */ /* * 変数を並べてて宣言すると (偶然..) アドレスが連続していた.. */ printf ( "変数 cvar のアドレスは 16 進数表現で %x です。\n", get_variable_address( cvar ) ); printf ( "変数 dvar のアドレスは 16 進数表現で %x です。\n", get_variable_address( dvar ) ); printf ( "変数 evar のアドレスは 16 進数表現で %x です。\n", get_variable_address( evar ) ); /* メモリ | | ... | | +-------+ cvar <-> 663615ed| 'c' | <= "cD" +-------+ dvar <-> 663615ee| 'D' | +-------+ evar <-> 663615ef| '\0'| +-------+ | | +-------+ | | */ /* * 変数をアドレスを利用して参照 */ cvar = 'c'; /* 変数 cvar に、値 'c' を代入 */ dvar = 'D'; /* 変数 dvar に、値 'D' を代入 */ evar = '\0'; /* 変数 evar に、値 '\0' を代入 */ printf ( "cvar の所から記録されている文字列は (%s) です。\n", get_variable_address( cvar ) ); /* コンピュータから見れば "cD" も、 上のようにたまたま、連続したセルに 'c', 'D', '\0' のは 区別できない(し、区別しない) */ /* !! C 言語の振る舞い -> 変数の値の変化 -> メモリのセルの値の変化 */ /* * アドレス経由で、変数の内容を変更 */ set_variable_value_at ( get_variable_address( cvar ) + 1, 'x' ); /* 変数 cvar のアドレスの次のアドレスは dvar のアドレスなので.. */ printf ( "cvar に記録されている文字は %c です。\n", cvar ); /* 結果的に、dvar の内容が書き変わる */ printf ( "dvar に記録されている文字は %c です。\n", dvar ); /* * */ return 0; } /* * */
/* * 2017/11/24 sample-008.c */ /* * メモリモデルの理解 (8) * * 利用方法 * コンパイル * cc -I ~/c/include -c sample-008.c * リンク * cc -o sample-008.exe sample-008.c * 実行 * ./sample-008.exe */ #include <stdio.h> #include "s_variable.h" /* memory モデルを理解するための関数定義 */ /* * main */ int main ( int argc, char *argv[] ) { /* * C 言語の変数のメモリモデルによる理解 */ char carray[3]; /* char 型の一次元配列 carray の宣言 (サイズは 3) */ /* carray[0], carray[1], carray[2] の三つの変数を.. */ /* この変数が、メモリ上で、連続したアドレスに割り当てられる */ /* -> アドレスを「計算で得る」事ができる */ /* -> 添え字に「式」が使える */ /* a[10] -> a[0] から 10 こはなれている a[10] のアドレスは a[0] アドレスに 10 を加える *(a + 10) -> 「*(ポインター剥ぎ)」 -> アドレスを利用してセルを参照 */ /* 意味的には char carry[0]; -- cvar char carry[1]; -- dvar char carry[2]; -- evar のように考えて良い (cf. sample-007.c) */ /* * 配列の要素のアドレスは連続している事が保証される */ printf ( "変数 carray[0] のアドレスは 16 進数表現で %x です。\n", get_variable_address( carray[0] ) ); printf ( "変数 carray[1] のアドレスは 16 進数表現で %x です。\n", get_variable_address( carray[1] ) ); printf ( "変数 carray[2] のアドレスは 16 進数表現で %x です。\n", get_variable_address( carray[2] ) ); /* * 変数をアドレスを利用して参照 */ carray[0] = 'c'; /* 変数 carray[0] に、値 'c' を代入 */ carray[1] = 'D'; /* 変数 carray[1] に、値 'D' を代入 */ carray[2] = '\0'; /* 変数 carray[2] に、値 '\0' を代入 */ printf ( "carray[0] の所から記録されている文字列は (%s) です。\n", get_variable_address( carray[0] ) ); /* * アドレス経由で、変数の内容を変更 */ set_variable_value_at ( get_variable_address( carray[0] ) + 1, 'x' ); /* 変数 carray[0] のアドレスの次のアドレスは carray[1] のアドレスなので.. */ printf ( "carray[0] に記録されている文字は %c です。\n", carray[0] ); /* 結果的に、carray[1] の内容が書き変わる */ printf ( "carray[1] に記録されている文字は %c です。\n", carray[1] ); /* * */ return 0; } /* * */
/* * 2017/11/24 sample-011.c */ /* * アドレス演算子「&」と間接演算子「*」 * * 利用方法 * コンパイル * cc -c sample-011.c * リンク * cc -o sample-011.exe sample-011.c * 実行 * ./sample-011.exe */ #include <stdio.h> /* * main */ int main ( int argc, char *argv[] ) { /* * アドレス演算子「&」と間接演算子「*」 */ char carray[3] = "AB"; /* { 'A', 'B', '\0' } */ /* メモリ | | ... | | +-------+ carray[0] <-> | 'A' | <= "cD" +-------+ carray[1] <-> | 'B' | +-------+ earray[2] <-> | '\0'| +-------+ | | */ /* * 添字による参照 */ printf ( "carray[0] = %c\n", carray[0] ); /* carray[0] は、carray[0] に対応したセルへの参照 carray[0] のアドレス(番地)を利用して参照が行われる */ printf ( "carray[1] = %c\n", carray[1] ); /* * 間接演算子による参照 */ printf ( "*carray = %c\n", *carray ); /* *carray <-> *(carray + 0) <-> carray[0] <-> セル参照 carray : 配列名 -> アドレスそのもの 「*」: アドレスを利用して、セルを指定する仕組み -> アドレスがないと利用できない仕組み <- アドレスを得る仕組みも必要 変数名からアドレスを得る仕組み「&」 */ printf ( "*(carray+1) = %c\n", *(carray+1) ); /* * address の比較 */ printf ( "&carray[0] = %x\n", &carray[0] ); /* 「&carray[0]」は、変数 carray[0]に 「&」をつけたもの */ printf ( "carray = %x\n", carray ); /* carray は carray[0] のアドレスを表現している */ /* 一般に、配列名は、実は、最初要素のアドレス(番地)を表す */ /* 二つの表現 carray, &carray[0] は同じ値(セルのアドレス) になる */ /* * 「&」と「*」は逆演算子 */ printf ( "carray = %x\n", carray ); printf ( "&*carray = %x\n", &*carray ); printf ( "carray[0] = %c\n", carray[0] ); printf ( "*&carray[0] = %c\n", *&carray[0] ); /* * */ return 0; } /* * */
?v?Z?@???A??????????????? ??w?????^???????? PC ?????A 8 G byte ?????????????????? 1 byte ( 8 bit ) ??? 0 ?` 255 (2^8=256 ???????????)????????l?????????L?^????? ?????????A ???L?^????? ?????o??????????? !! C ?????u????v????????? (???_????????..) ?u????v??A????u????????Z???v????O??????????? !! C ?????u????(???x??)?v !! ????v???????A?u???????v???u????v???????? [??i??] 1 byte = 8 bit -> 8 ??? bit ?????? bit -> 2 ????????????L?^????? (Yes/No, ?^/?U, ????/?j??, ?\/??, ????/?J, ??/??, ?P/??.., ) 0/1 -> 0 ?? 1 ???????????????? 1 ??????? byte -> 0/1 ??????????? 8 ??????? 00000000 0 00000001 1 00000010 2 00000011 3 ... 11111110 11111111 255 --------------- 2^8 256 00000000 = 0*2^7+0*2^6+0*2^5+0*2^4+0*2^3+0*2^2+2^1*0+2^0*0 = 0 00000001 = 0*2^7+0*2^6+0*2^5+0*2^4+0*2^3+0*2^2+2^1*0+2^0*1 = 1 00000011 = 0*2^7+0*2^6+0*2^5+0*2^4+0*2^3+0*2^2+2^1*1+2^0*1 = 0 + 0+ 0+ 0+ 0+ 0+ 2+ 1 = 3 11111111 = 1*2^7+1*2^6+1*2^5+1*2^4+1*2^3+1*2^2+2^1*1+2^1*1 = 128 + 64+ 32+ 18+ 8+ 4+ 2+ 1 = 255 -> 0/1 ?????\?????? bit?@???A2 ?i???????????? 1 00000001 (1) +) 00000001 (1) -------------- 00000010 (2) 1111111 11111111 (255) +) 00000001 (1) -------------- 100000000 ^ 9 bit ?? -> ??????? -------------- 00000000 (0) ( 8 bit ?????????????A?I?[?o?[?t???[????) # ??i????????u?R?[?f?B???O?v # on/off ????т?A?????l???\??????? # ?R???s???[?^???u???v???L?^??????R # ?d?C??Aon/off ???\????????? ??????(?Z??)??A?u(C ?????)????v????W C ?????u????v??A ????????(????????^??T?C?Y??????A??????)?Z?????? # cf. ?u?^??T?C?Y?v??usizeof(?^)?v??????? byte ?? # ????Asizeof(char) == 1 ## ?b????P???????? char ?^???????????l???? C ???? ?v?Z?@????? ??? ?????? +-------+ 0 | | +-------+ 1 | | +-------+ | | +-------+ | | ... | | +-------+ cvar <-> 7310651e| | +-------+ dvar <-> 7310651f| | +-------+ | | +-------+ | | ... | | +-------+ | | +-------+ fff...f | | +-------+ C ???? "abc" <-> { 'a', 'b', 'c', '\0' } sizeof ( "abc" ) = 4 "abc" ??A?A?????? 4 ???Z????\?????????? ?????? | | ... | | +-------+ "abc" <-> 400678 | 'a' | +-------+ "bc" <-> 400679 | 'b' | +-------+ "c" <-> 40067a | 'c' | +-------+ "" <-> 40067b | '\0'| +-------+ | | +-------+ | | ... | | +-------+ [????????] ?????????f?? 1 byte ????L?^?????Z????????B ?????????????????? ???????Z?????A??n(?A?h???X)?????????? ?Z???????A?A?h???X??p????Q??E??X????? ??X??Z????A??????????Achar ?^??????????U?????????? ! ????b??t??A?Z??????????AC ????? char ?^??????U????????????? C ?????????????????f?? C ?????????A????T?C?Y??????Z????????????? ?????A?h???X(=????????????Z????A?h???X)???????? ????????A?h???X??p????A?Z??(=???)?l?????????? ?I?u?W?F?N?g?w?? | class (method) | ?葱???^???? | | | (?A?N?Z?X????) | C ??????? | | | | ?|?C???^ (?????) ?A?Z???u?? | | | | | (????) | | | ?@?B?? | ?v?Z?@??????? (??n??Z??) sample-006.c ??????A?h???X???????????(??????Z???????????????) ???????????z?? ?z?????O -> ?l?????? -> ?z???A?A?h???X(??n)?????? => ?A?h???X??u?l?v????A??????????A?l?????? ?u&?v??A?????????A???????????????Z????A?h???X??????? scanf ??A????A??????l???????????????A ???????O??u???v??t???????R ?u???v??????邱?????A?????A?h???X???v?Z????? ?A?h???X??l????Ascanf ?????n???????????? scanf ??A?????A?h???X??p????A????l???X ?A?h???X??p????????l????X????? => ???????A?C??????????????(???????????????????l????????????\????????) => ???????A?u????v (???????) (1 ??????K) ????????Z??????????A?????A?Z?????? ?????l???????A?A?h???X???????? (2 ??????K) ??????? & ???g????A?????A?h???X?????o???? ????A?h???X???? * ?????????A???(?????????Z??)??????? * ?? & ??t???Z????????? scanf ???( ?l???????????A?K???u&?v??t????)???????B
Download : 20171124-01.c
/* * 課題 20171124-01 * * 2017/11/24 20171124-01-QQQQ.c * * メモリ操作での和 * s_memory.h を利用し、 * 100 番地の内容と 101 番地の内容の和を * 102 番地に入れるプログラムを作成しなさい */ /* * 利用方法 * コンパイル * cc -I ~/c/include -o BASENAME.exe 20171124-01-QQQQ.c * 実行 * ./BASENAME.exe */ #include <stdio.h> #include "s_memory.h" /* * print_memory_value * 指定された address の記憶セルの内容を画面に出力する */ void print_memory_value ( int address ) { printf ( "%d 番地のセルに記録されている数値は %d です。\n", address, get_memory_value_at ( address ) /* 値の取出し */ ); } /* * */ int main ( int argc, char *argv[] ) { /* 値の設定 */ /* * メモリセルの容量 */ set_memory_value_at ( 100, 12 ); /* 100 番地のセルに 12 を記録する */ set_memory_value_at ( 101, 78 ); /* 100 番地のセルに 78 を記録する */ /* * 100 番地の値と 101 番地の値の和を 102 番地にいれる */ /* ** この部分を完成させなさい */ /* * 結果の出力 */ print_memory_value ( 102 ); /* 102 番地のセルの内容を出力 */ return 0; } /* * */
2.3 9.1 5.9 2.7 3.2
$ ./20171124-01-QQQQ.exe 102 番地のセルに記録されている数値は 90 です。 $
Download : 20171124-02.c
/* * 課題 20171124-02 * * 2017/11/24 20171124-02-QQQQ.c * * アドレスを利用した間接参照 * 代入文を利用せず、s_variable.h を利用して、 * 変数 cvar の値を 1 だけふやせ */ #include <stdio.h> #include "s_variable.h" /* memory モデルを理解するための関数定義 */ /* * 利用方法 * コンパイル * cc -I ~/c/include -o BASENAME.exe 20171124-02-QQQQ.c * 実行 * ./BASENAME.exe */ int main ( void ) { /* * C 言語の変数のメモリモデルによる理解 */ char cvar = 'p'; /* char 型の変数 cvar の宣言 */ printf ( "cvar は %c です。\n", cvar ); /* ** この部分を完成させなさい */ printf ( "cvar は %c になりました。\n", cvar ); /* * */ return 0; } /* * */
123 987 456
$ ./20171124-02-QQQQ.exe cvar は p です。 cvar は q になりました。 $