#include <stdio.h> int main(void) { int n = 1; int i; for ( i = 0; i < 100; i++ ) { printf ( "2^%d = %d\n", i, n ); n = n * 2; } return 0; }
#include <stdio.h> int main(void) { int i; printf ( "%x\n", &i ); /* &i で、変数 i に対応したメモリのアドレスが得られる */ i = 10; printf ( "%d, %d\n", i, *(&i) ); /* i と *(&i) は同じに振舞う */ *(&i) = 99; printf ( "%d, %d\n", i, *(&i) ); /* i と *(&i) は同じに振舞う */ return 0; }
#include <stdio.h> /* int i; int j; -> int i, j; int *i; int *j; -> int *i, *j; */ void sub ( int *ai ) { /* (*ai) -> int */ /* int* ai */ /* int * ai */ /* int*ai */ *ai = 999; /* ai <-> &i : *au <-> *(&i) <-> i */ /* だから 「i = 999」と同じ */ } int main(void) { int i; i = 10; printf ( "i=%d\n", i ); sub ( &i ); printf ( "i=%d\n", i ); return 0; }
#include <stdio.h> int main(void) { int i; int j; printf ( "&i = %x\n", &i ); printf ( "&j = %x\n", &j ); return 0; }
#include <stdio.h> void sub(void) { int i; int j; printf ( "Sub:\n" ); printf ( "&i = %x\n", &i ); printf ( "&j = %x\n", &j ); } int main(void) { int i; int j; printf ( "Main:\n" ); printf ( "&i = %x\n", &i ); printf ( "&j = %x\n", &j ); sub(); return 0; }
#include <stdio.h> void sub( int k ) { int i; int j; if ( k > 0 ) { printf ( "Sub: k=%d\n", k ); printf ( "&i = %x\n", &i ); printf ( "&j = %x\n", &j ); sub ( k - 1 ); } } int main(void) { int i; int j; printf ( "Main:\n" ); printf ( "&i = %x\n", &i ); printf ( "&j = %x\n", &j ); sub(5); return 0; }
#include <stdio.h> void sub1(void) { int i = 1; int j; printf ( "Sub1:\n" ); printf ( "&i = %x, i = %d\n", &i, i ); printf ( "&j = %x, j = %d\n", &j, j ); } void sub2(void) { int i; int j = 10; printf ( "Sub2:\n" ); printf ( "&i = %x, i = %d\n", &i, i ); printf ( "&j = %x, j = %d\n", &j, j ); } int main(void) { int i; int j; printf ( "Main:\n" ); printf ( "&i = %x\n", &i ); printf ( "&j = %x\n", &j ); sub1(); sub2(); sub1(); return 0; }
#include <stdio.h> void sub1 ( int i ) { printf ( "sub1: &i = %x, i = %d\n", &i, i ); }
#include <stdio.h> void sub2 ( char i ) { printf ( "sub2: &i = %x, i = %d\n", &i, i ); printf ( "sub2: (&i+1) = %x, i = %d\n", &i+1, *(&i+1) ); printf ( "sub2: %d\n", (256 + i) + (*(&i+1))*256 (*(&i+2))*256*256 (*(&i+3))*256*256*256 ); }
#include <stdio.h> int main(void){ sub1(1000); sub2(1000); return 0; }
#include <stdio.h> void sub(char i) { int j; for ( j = 0; j < sizeof ( double ); j++ ) { printf ( "&i + j = %x, *(&i + j) = %d\n", &i + j, *(&i + j) ); } }
#include <stdio.h> int main(void) { sub ( 2.0 ); /* 0.25 -> 1.0 * 2^-2 1+11+52 +-+---+----+ |0|-2 |1.0 | +-+---+----+ -2 -> 11111110 1.0 -> 1.000000000 -> 000000000 (先頭の 1 はケチる) +-+---+----+ |s|exp|frac| +-+---+----+ 1 11 52 H L +-+----------+-----------------------------+ |0|1111111110|000000000000..000000000000000| +-+----------+-----------------------------+ | | | .... | +--------+ |00000000| L +--------+ |00000000| +--------+ |00000000| +--------+ |00000000| +--------+ |00000000| +--------+ |00000000| +--------+ |11100000| +--------+ |01111111| H +--------+ */ return 0; }
int 型 ( 32bit = 4 byte ) Memory 数 00000000000000000000000000000001 1 2^0 00000000000000000000000000000010 2 2^1 00000000000000000000000000000100 4 2^2 .. 01000000000000000000000000000000 1073741824 2^30 10000000000000000000000000000000 -2147483648 2^31 100000000000000000000000000000000 0 2^32 ^ ここはない === 復習 変数 : 情報を記録 これは、メモリの複数のセルの列(組)で実現されている メモリ セルの集まり セル : 1 つで 1 byte / それぞれアドレスがある C 言語 変数名の前に & をつけると、アドレスが得られる & でえられた、ものに * をつけると元に変数と同じに振舞う & で得られた値は、「値」なので、関数の引数や、返り価にできる 通常、変数が異れば、異るメモリにはいる 異るメモリなので、異るアドレスを物 C のプログラムを理解する場合の二つの「状況」 プログラムを書いている(コンパイルしている)状況 main i と sub i が異る プログラムが実行されている状況 i に割り当てられるアドレスが変る 関数呼出がおきると、 その時点で、変数に対応するメモリ割当がおきる 関数からかえると、そのメモリは、再利用される ※同じメモリを再利用するので、元の値がゴミとして残っている 必ず、変数は、初期化(掃除)をして利用する == main() sub1(1000) 1000 = 256*3 + 232 -> sub1(int i) i +-------------+ | 232 | -24 +-------------+ | 3 | +-------------+ | 0 | +-------------+ | 0 | +-------------+ sub1() printf ( .. i ) ; int i (4 つ全部) sub2(1000) 1000 = 256*3 + 232 i +-------------+ &i | 232 | -24 +-------------+ &i+1 | 3 | +-------------+ | 0 | +-------------+ | 0 | +-------------+ sub2() printf ( .. i ) ; char i (1 つ) == 変数が、メモリに対応つけられる 対応は、実行時に、関数が呼び出された時点で行われる ※ 関数からかえると、その割当は解消される ー>同じメモリが異る変数に割り当てられる事がある 関数の引数 メモリ割り当てられるが、その値を参照する時には、 引数型宣言に基いて行われる 渡した値の型と受け取る値の型が異ると、 ことなったものを受け取る事なる 関数の型宣言に注意 逆に、一つ値を、型情報利用して異るようにみることができる
課題プログラム内の「/*名前:ここ*/」の部分を書き換え「/*この部分を完成させなさい*/」の部分にプログラムを追加して、プログラムを完成させます。
Download : 20151204-01.c ( SJIS 版 )
/* * 20151204-01-QQQQ.c * ポインターを利用して、整数変数の値を正値にする */ #include <stdio.h> /* * to_positive_int_variable ( int *iVarPtr ) * 指定された整数型の変数の値を正値になるようにする * int *iVarPtr : 整数型変数へのポインター値 */ void to_positive_int_variable ( int *iVarPtr ) { if ( *iVarPtr < 0 ) { /* もし、整数型変数の値が負ならば.. */ /* その値の符号を変更して、元の変数に代入する */ /* ** この部分を完成させなさい */ } /* そうでなければ、何もしない.. */ } /* * */ int main ( int argc, char *argv[] ) { int pVar = 5; /* 正の値を持つ整数型変数 */ int nVar = -2; /* 負の値を持つ整数型変数 */ int zVar = 0; /* 零の値を持つ整数型変数 */ /* pVar */ printf ( "前 : pVar = %d\n", pVar ); to_positive_int_variable ( &pVar ); /* 引数はポインター値を指定する */ printf ( "後 : pVar = %d\n", pVar ); /* nVar */ printf ( "前 : nVar = %d\n", nVar ); /* ** この部分を完成させなさい */ printf ( "後 : nVar = %d\n", nVar ); /* zVar */ printf ( "前 : zVar = %d\n", zVar ); /* ** この部分を完成させなさい */ printf ( "後 : zVar = %d\n", zVar ); return 0; } /* * */
2.3 9.1 5.9 2.7 3.2
$ ./20151204-01-QQQQ.exe 前 : pVar = 5 後 : pVar = 5 前 : nVar = -2 後 : nVar = 2 前 : zVar = 0 後 : zVar = 0 $