Powered by SmartDoc

ソフトウェア概論A/B (2017/11/24)
Ver. 1.0

2017年11月24日
栗野 俊一
kurino@math.cst.nihon-u.ac.jp
http://edu-gw2.math.cst.nihon-u.ac.jp/~kurino/2017/soft/soft.html
ソフトウェア概論 A/B2017年11月24日 の資料

目次

講義資料

当日の OHP 資料

Download

  1. s_print.hと同じフォルダに保存する。
  2. s_print.hと同じフォルダに保存する。

講義で利用するサンプルプログラム

Download : sample-001.c

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.c の実行結果
$ ./sample-001.exe
100 番地のセルに記録されている数値は 1 です。
101 番地のセルに記録されている数値は 10 です。
$ 

Download : sample-002.c

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.c の実行結果
$ ./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

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.c の実行結果
$ ./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

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.c の実行結果
$ ./sample-004.exe
100 番地のセルに 0 を記録。
100 番地のセルに記録されている数値は 0 です。
100 番地のセルに 100 を記録。
100 番地のセルに記録されている数値は 100 です。
100 番地のセルに 255 を記録。
100 番地のセルに記録されている数値は 255 です。
--------------------------------------
100 番地のセルに 300 を記録。
100 番地のセルに記録されている数値は 44 です。
$ 

Download : sample-005.c

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.c の実行結果
$ ./sample-005.exe
変数 cvar のアドレスは 16 進数表現で 1efe598e です。
変数 dvar のアドレスは 16 進数表現で 1efe598f です。
変数 cvar に記録されている文字は c です。
変数 dvar に記録されている文字は D です。
cvar は X です。
dvar は y です。
$ 

Download : sample-006.c

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.c の実行結果
$ ./sample-006.exe
文字列 "abc" のアドレスは 16 進数表現で 401480 です。
文字列 "abc" の先頭の文字は a  です。
文字列 "abc" の先頭の次の文字は b です。
文字列 "abc" の先頭の次の次の文字は c です。
$ 

Download : sample-007.c

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.c の実行結果
$ ./sample-007.exe
変数 cvar のアドレスは 16 進数表現で 5d9978bd です。
変数 dvar のアドレスは 16 進数表現で 5d9978be です。
変数 evar のアドレスは 16 進数表現で 5d9978bf です。
cvar の所から記録されている文字列は (cD) です。
cvar に記録されている文字は c です。
dvar に記録されている文字は x です。
$ 

Download : sample-008.c

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.c の実行結果
$ ./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

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.c の実行結果
$ ./sample-009.exe
carray[0] の所から記録されている文字列は (cD) です。
carray が表現している文字列は (cD) です。
carray が表現している文字列は (cU) です。
carray が表現している文字列は (pU) です。
$ 

Download : sample-010.c

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.c の実行結果
$ ./sample-010.exe
carray[0] は A です。
carray[1] は B です。
$ 

Download : sample-011.c

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.c の実行結果
$ ./sample-011.exe
carray[0] は A です。
carray[1] は B です。
$ 

Download : sample-012.c

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.c の実行結果
$ ./sample-012.exe
oxx
xoo
oxx
$ 

Download : sample-013.c

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.c の実行結果
$ ./sample-013.exe
oxx
xoo
oxx
$ 

Download : sample-014.c

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.c の実行結果
$ ./sample-014.exe
oxx
xoo
oxx
$ 

Download : sample-015.c

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.c の実行結果
$ ./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

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.c の実行結果
$ ./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

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

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.c の実行結果
$ ./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

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.c の実行結果
$ ./sample-018.exe
fact(5)=120
$ 

Download : sample-019.c

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.c の実行結果
$ ./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

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.c の実行結果
$ ./sample-020.exe
a = 2, &a = afaacc1c
b = 4, &b = afaacc18
$ 

Download : sample-021.c

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.c の実行結果
$ ./sample-021.exe
a = 2, &a = 41706cec
b = 4, &b = 41706ce8
*(&b-1) = 0, &b-1 = 41706ce4
a = 2
$ 

Download : sample-022.c

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.c の実行結果
$ ./sample-022.exe
a = 1, &a = c9d9fbdc
*(&a+1) = -2023167072, &a + 1 = c9d9fbe0
*(&a+2) = 11116, &a + 2 = c9d9fbe4
$ 

Download : sample-023.c

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.c の実行結果
$ ./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

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.c の実行結果
$ ./sample-024.exe

i = , j = 
1 st = , 2nd = , 3rd =  
$ 

Download : sample-025.c

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.c の実行結果
$ ./sample-025.exe
99
i=10, j=20, k=90
i=10, j=20, k=90
$ 

Download : sample-026.c

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.c の実行結果
$ ./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

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.c の実行結果
$ ./sample-027.exe
a=-12.340000
a=      -12.3400000000
$ 

Download : sample-028.c

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.c の実行結果
$ ./sample-028.exe < sample-028.in
i の値を入力してください 10
入力された i の値は 10 でした
$ 

講議中に作成したプログラム

本日の課題

課題 20171124-01 : メモリ操作での和

Download : 20171124-01.c

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.c の実行結果
$ ./20171124-01-QQQQ.exe
102 番地のセルに記録されている数値は 90 です。
$ 

課題 20171124-02 : アドレスを利用した間接参照

Download : 20171124-02.c

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.c の実行結果
$ ./20171124-02-QQQQ.exe
cvar は p です。
cvar は q になりました。
$ 

Links

関連 Link