第6章 ポインタ ポインタが分からずにC言語を投げ出す人が数多くいます。 その半面、使いこなせば強力な武器となります。 しっかりと学習していきましょう C 言語 最難関文法 C 言語 最難関文法 1 第 6 章 ポインタ.

Slides:



Advertisements
Similar presentations
構造体 構造体とは? 複数のデータをパックしたもの。 新しい “ 型 “ として使用できる. 構造体 キーワード struct strcut は構造体を宣言する命令。 struct { double x,y; }a,b,c; ↑ ここまでが宣 言 ← この形式で、構造体 a,b,c, を定 義.
Advertisements

メモリとポインタ. プログラムの前提 コンピュータは、0と1で計算をし、 0と1でデータを保存している。 メモリを学ぶのに必要な知識である。
第 2 章 数値の入力と変数 scanf と変数をやります 第 2 章 数値の入力と変数 1. 以下のプログラムを実行してみよう  C 言語では文の最後に「 ; 」(セミコロン)が付きます 第 2 章 数値の入力と変数 2 #include int main() { int x; x = 3; printf("x.
C 言語講座 第 7 回 ポインター. メモリとアドレス(ポインターの前 に) コンピュータのメモリには 1 バイトずつ 0 番地、 1 番地、 2 番地・・・というように 住所が割り当てられている この住所をアドレスという。 メモリはデータをしまうもので それを引き出すためには メモリに番号(アドレス)を振っておけばよいな.
コンピュータープログラミング(C言語)(3) 1.関数と分割コンパイル (復習) 2.キーボード入力
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
第2章 数値の入力と変数 scanfと変数をやります.
データ構造とアルゴリズム 第10回 mallocとfree
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
プログラミング演習(2組) 第12回
プログラミング言語論 第6回 型 情報工学科 篠埜 功.
C言語講座 第4回 ポインタ.
構造体.
第4回放送授業.
プログラミング演習Ⅰ 課題2 10進数と2進数 2回目.
第3回 配列,構造体,ポインタ ~ データ構造について学ぶための基礎~
岩村雅一 知能情報工学演習I 第8回(後半第2回) 岩村雅一
オセロを作るとします。 各マスの状態を保存するために64個の変数が必要です。 でも64個も変数を作るのはめんどくさいですよね。
C言語講座 第3回 ポインタ、配列.
プログラミング論 関数ポインタ と 応用(qsort)
ちょっとした練習問題① 配列iroを['R', 'W', 'R', 'R', 'W' , 'W' , 'W']を宣言して、「W」のときの配列の番号をprintfで表示するようなプログラムを記述しなさい。
プログラミング2 関数
関数とポインタ 値呼び出しと参照呼び出し swapのいろいろ 関数引数 数値積分
関数の定義.
第10回関数 Ⅱ (ローカル変数とスコープ).
プログラミング 4 記憶の割り付け.
アルゴリズムとデータ構造 補足資料11-1 「mallocとfree」
第10章 これはかなり大変な事項!! ~ポインタ~
プログラミング入門2 第2回 型と演算 条件分岐 篠埜 功.
メモリの準備 メモリには、その準備の方法で2種類ある。 静的変数: コンパイル時にすでにメモリのサイズがわかっているもの。 普通の変数宣言
プログラミング入門2 第11回 情報工学科 篠埜 功.
第7回 プログラミングⅡ 第7回
復習 前回の関数のまとめ(1) 関数はmain()関数または他の関数から呼び出されて実行される.
アルゴリズムとデータ構造 補足資料5-1 「メモリとポインタ」
高度プログラミング演習 (08).
地域情報学 C言語プログラミング 第5回 ポインタ、関数、ファイル入出力 2017年11月17日
P n ポインタの基礎 5 q m 5 7 int* p; int 型の変数を指すポインタ int* q; int 型の変数を指すポインタ int n=5, m=7; int 型の変数 int array[3]; int* pArray[3]; p = &n; ポインタにアドレスを代入しているのでOK.
09: ポインタ・文字列 C プログラミング入門 総機1 (月1) Linux にログインし、以下の講義ページ を開いておくこと
関数への道.
岩村雅一 知能情報工学演習I 第12回(C言語第6回) 岩村雅一
配列変数とポインタ 静的確保と動的確保 ポインタ配列 2次元配列 時間計測 第1回レポートの課題
メモリとメモリアドレス, ポインタ変数,関数へのポインタ渡し
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
プログラミング言語論 第六回 理工学部 情報システム工学科 新田直也.
C言語 はじめに 2016年 吉田研究室.
構造体と共用体.
15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
データ構造とアルゴリズム 第11回 リスト構造(1)
プログラミング入門2 第9回 ポインタ 情報工学科 篠埜 功.
文字列へのポインタの配列 static char *lines[MAXLINES]; lines[0] NULL
ポインタとポインタを用いた関数定義.
情報基礎演習B 後半第2回 担当 岩村 TA 谷本君.
プログラミング論 ポインタ
11.1 標準ライブラリ関数 11.2 関数呼び出しのオーバーヘッド 11.3 大域変数 11.4 プロトタイプ宣言 11.5 関数引数
ネットワーク・プログラミング Cプログラミングの基礎.
第5回 プログラミングⅡ 第5回
第2章 printf(“変数と入力”); scanf(“%d”,&num);
プログラミング 4 文字列.
岩村雅一 知能情報工学演習I 第12回(後半第6回) 岩村雅一
第7章 そろそろ int 以外も使ってみよう! ~データ型 double , bool~
2005年度 データ構造とアルゴリズム 第2回 「C言語の復習:配列」
プログラミング演習II 2004年11月 2日(第3回) 理学部数学科・木村巌.
printf・scanf・変数・四則演算
第2章 数値の入力と変数 scanfと変数をやります.
計算技術研究会 第5回 C言語勉強会 関数(function)を使う
C言語講座 四則演算  if ,  switch 制御文.
プログラミング演習II 2003年10月29日(第2,3回) 木村巌.
分岐(If-Else, Else if, Switch) ループ(While, For, Do-while)
プログラミング 3 ポインタ(1).
Presentation transcript:

第6章 ポインタ ポインタが分からずにC言語を投げ出す人が数多くいます。 その半面、使いこなせば強力な武器となります。 しっかりと学習していきましょう C 言語 最難関文法 C 言語 最難関文法 1 第 6 章 ポインタ

変数とメモリ int a; という文が実行された時、どうなるでしょうか?  宣言するとコンピュータのメモリと呼ばれる 記憶領域内に4Byte分の領域が確保される  代入すれば、その領域に値が保存される  参照すると、その領域からデータが取得される a = 6;printf("%d“,a); メモリ 6 6 場所確保 6 を保存! 6 が保存されてる から 6 を表示 宣言代入参照 2 第 6 章 ポインタ

アドレス(1)  変数を宣言すると場所が確保される  その確保された場所を表す住所のようなものをアドレスという メモリ 6 ここの住所は 008F3D29 番地です 変数のアドレスの取得はアドレス演算子で取得できる 演算子意味優先順位種類 & アドレス取得 3 単項 また、アドレスの表示の際はフォーマット指定子 %p を用いる 3 第 6 章 ポインタ

アドレス(2) #include int main(void){ int a; double b; %p%p&a&b printf("a のアドレスは %p,b のアドレスは %p です \n”, &a, &b); return 0; } #include int main(void){ int a; double b; %p%p&a&b printf("a のアドレスは %p,b のアドレスは %p です \n”, &a, &b); return 0; } 実行結果は毎回異なります 次のプログラムを実行しよう 4 第 6 章 ポインタ

ポインタ変数(1)  アドレスを格納する変数のことをポインタ変数という  ポインタ変数は以下のように宣言できる 文法 データ型 * ポインタ変数名 ; OR ここでのデータ型は、代入したアドレスにある変数のデータ型 メモリ 6 int a; 008F3D29 int* pa; int 型ポインタ変数には int 型変数のアドレス のみ代入可能 6.0 double b; 5 第 6 章 ポインタ

ポインタ変数(2) 次のプログラムを実行しよう #include int main(void){ int a; double b; int* pa = &a; double* pb = &b; printf("a のアドレスは %p,b のアドレスは %p です \n", pa, pb); return 0; } #include int main(void){ int a; double b; int* pa = &a; double* pb = &b; printf("a のアドレスは %p,b のアドレスは %p です \n", pa, pb); return 0; } 実行結果は毎回異なります 6 第 6 章 ポインタ

間接参照(1)  ある特定のアドレスにある、変数の値を取得することを 間接参照という メモリ 6 アドレス : 008F3D29  008F3D29にある変数の 値はなんだろう?  6だ! 間接参照には間接参照演算子を用いる。 演算子意味優先順位種類 * 間接参照 3 単項 ポインタ変数の前に間接参照演算子を付けると値が取得できる 7 第 6 章 ポインタ

間接参照(2) 次のプログラムを実行しよう #include int main(void){ int a; int* pa; pa = &a; a = 6; *pa printf(" アドレス %p にある変数の値は %d です \n", pa, *pa); return 0; } #include int main(void){ int a; int* pa; pa = &a; a = 6; *pa printf(" アドレス %p にある変数の値は %d です \n", pa, *pa); return 0; } a&apa*pa 初め ???002FF730??? pa = &a???002FF730002FF730??? a = 66002FF 第 6 章 ポインタ

間接参照(3) 間接参照演算子を用いた代入も可能 メモリ 6 アドレス : 008F3D29 008F3D29 int* pa  ポインタ変数paに代入さ れてるアドレスに6を代 入しよう  結果的にaに6を代入して るのと同じだ int a *pa の値を参照したり、代入したりするのは、 変数 a の値を参照したり、代入したりするのと同じ *pa と a は同じものと考えてもよい 9 第 6 章 ポインタ

間接参照(4) 次のプログラムを実行しよう #include int main(void){ int a; int* pa; pa = &a; *pa = 6; printf(" 変数 a の値は %d です \n", a); return 0; } #include int main(void){ int a; int* pa; pa = &a; *pa = 6; printf(" 変数 a の値は %d です \n", a); return 0; } a&apa*pa 初め ???002FF730??? pa = &a???002FF730002FF730??? *pa = 66002FF 第 6 章 ポインタ

間接参照(5) 実行しないで下さい!! 次のプログラムを 実行しないで下さい!! #include int main(void){ int* pa; *pa = 6; return 0; } #include int main(void){ int* pa; *pa = 6; return 0; }  paに何が入ってるか分からない!  ひょっとしたら、PCを動かすのに 重要な情報を保持している変数の アドレスが入っているかも  6を代入した瞬間にそのデータが 壊れる  PCがおかしくなる たぶん安全装置が働きますが、念のためやめてね 11 第 6 章 ポインタ

ポインタのポインタ(1) ポインタ変数にも当然アドレスが存在します メモリ 6 アドレス : 008F3D29 008F3D29 アドレス : 002FF730 当然、ポインタのアドレスを代入できる変数も存在します 文法 データ型 ** ポインタ変数名 ; OR 12 第 6 章 ポインタ

ポインタのポインタ(2) #include int main(void){ int a; int* pa; int** ppa; pa = &a; ppa = &pa; **ppa = 6; printf(" 変数 a の値は %d です \n", a); return 0; } #include int main(void){ int a; int* pa; int** ppa; pa = &a; ppa = &pa; **ppa = 6; printf(" 変数 a の値は %d です \n", a); return 0; } 変数 a と *pa は同じものとして見てもよい また pa と *ppa も同じものとして見てもよい →*pa と **ppa も同じものとして見てもよい 変数 a と *pa と **ppa は同じものとして見てもよい 13 第 6 章 ポインタ

ポインタのポインタ(3) a&apa*pa&pappa*ppa**ppa 初め ?2FF730????3DA532??? pa=&a?2FF7302FF730?3DA532??? ppa=&pa?2FF730 ?3DA5323DA5322FF730? **ppa=662FF730 63DA532 2FF7306 #include int main(void){ int a; int* pa; int** ppa; pa = &a; ppa = &pa; **ppa = 6; printf(" 変数 a の値は %d です \n", a); return 0; } #include int main(void){ int a; int* pa; int** ppa; pa = &a; ppa = &pa; **ppa = 6; printf(" 変数 a の値は %d です \n", a); return 0; } 14 第 6 章 ポインタ

ポインタと関数(1)  変数aと*paは同じように使える!  じゃあ別に変数aを使えば*paいらないよね? いらない文法があるわけありません! 変数 a のアドレスさえ分かっていれば、 変数 a のスコープ外であっても、変数 a を編集できるのです その仕組みをよく使うのが関数です 15 第 6 章 ポインタ

ポインタと関数(2) 次のプログラムを実行しよう #include // 指定した変数に 1 を足す関数 void increment(int* num){ (*num)++; } int main(void){ int a = 10; increment( &a ); printf("%d\n",a); return 0; } #include // 指定した変数に 1 を足す関数 void increment(int* num){ (*num)++; } int main(void){ int a = 10; increment( &a ); printf("%d\n",a); return 0; }  ポインタ変数numに 変数aのアドレスが入る  これを使えばスコープ外 でも変数aの編集が可能 #include int increment(int num){ num++; return num; } int main(void){ int a = 10; a = increment( a ); printf("%d\n",a); return 0; } #include int increment(int num){ num++; return num; } int main(void){ int a = 10; a = increment( a ); printf("%d\n",a); return 0; } これでもおんなじ結果に! でもこれだと出来ない プログラムもある!! 16 第 6 章 ポインタ

ポインタと関数(3) 点 (x,y) を原点中心に θ 回転させた点 (x2,y2) を取得する関数 を考える  戻り値がx2とy2の二つが必要  二つの戻り値を返す文法はない ポインタの出番 場所がないのでサンプルは次ページ 17 第 6 章 ポインタ

ポインタと関数(4) #include void rotation(double x,double y,double theta,double* x2, double* y2){ *x2 = x * cos(theta) - y * sin(theta); *y2 = x * sin(theta) + y * cos(theta); } int main(void){ double x, y, theta, x2, y2; printf("X 座標 "); scanf("%lf",&x); printf("Y 座標 "); scanf("%lf",&y); printf(" 角度 "); scanf("%lf",&theta); rotation(x, y, theta, &x2, &y2); printf("(%lf,%lf)---%lf(rad) 回転 →(%lf,%lf)\n", x, y, theta, x2, y2); return 0; } #include void rotation(double x,double y,double theta,double* x2, double* y2){ *x2 = x * cos(theta) - y * sin(theta); *y2 = x * sin(theta) + y * cos(theta); } int main(void){ double x, y, theta, x2, y2; printf("X 座標 "); scanf("%lf",&x); printf("Y 座標 "); scanf("%lf",&y); printf(" 角度 "); scanf("%lf",&theta); rotation(x, y, theta, &x2, &y2); printf("(%lf,%lf)---%lf(rad) 回転 →(%lf,%lf)\n", x, y, theta, x2, y2); return 0; } 18 第 6 章 ポインタ

ポインタと関数(5) さっきのページのプログラムで気づくことはなかったですか? scanf("%lf", &x ); 第2引数では変数のアドレスを送ってあげます。 そうすると、変数の値が書き換えられるのです。 time 関数もポインタを使って書くことが可能です time_t dateTime; NULL dateTime=time(NULL); time_t dateTime; NULL dateTime=time(NULL); time_t dateTime; &dateTime time(&dateTime); time_t dateTime; &dateTime time(&dateTime); 同じ意味 time 関数の本当の戻り値は time_t 型 time 関数の本当の戻り値は time_t 型 ところで NULL ってなんでしょう? 19 第 6 章 ポインタ

ヌルポインタ 次のプログラムを実行しよう #include int main(void){ printf("%p\n",NULL); return 0; } #include int main(void){ printf("%p\n",NULL); return 0; }  NULLとはアドレス0のこと  アドレス0は使わない決まりがある  NULLが送られてきたら、time関数の中で 「おかしいから代入しないでおこう」ってなる 20 第 6 章 ポインタ

他のポインタの使い道 もし、音楽を代入できるデータ型と再生する関数があったら  int型は4Byteだけど、音楽だと数十Mbyteになりそう  再生するたびに引数にそのデータをコピー  さすがに数十Mbyteもあるとコピーに時間がかかる アドレスをコピーするだけなら数 Byte で済む ポインタを使おう !! 21 第 6 章 ポインタ

ここまでのまとめ  変数の保存されてる場所をアドレスという  アドレスを保存できる変数をポインタ変数という  間接参照演算子で間接参照、代入が可能  ポインタで関数の引数を戻り値のような役割にできる  重いデータはポインタのコピーだけで済ます 22 第 6 章 ポインタ

練習問題 問1問1 問1問1 int 型変数 a,b のアドレスを引数として送ると、 a,b の値が入れ替わる関数を作れ 問2問2 問2問2 点 (x,y) を x 軸方向に a,y 軸方向に b 平行移動した 点 (x2,y2) を取得する関数を作れ 23 第 6 章 ポインタ