#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 $