about pointer

36
ポインタの話をしよう ロボ研 非定期勉強会

Upload: sho-iizuka

Post on 22-Jul-2015

281 views

Category:

Technology


3 download

TRANSCRIPT

ポインタの話をしようロボ研 非定期勉強会

本題に入る前に• 多くの人がポインタで挫折しています

• 「ポインタを理解してしまった人」は「ポインタを勘違いしている」状態を思い出すことができません

• どのような勘違いをしていたのか教えてください(ブログのネタになります)

今日話すこと1. ポインタって本当に使えないとダメ?

2. 【部内の】ポインタについて思うこと【反応】

3. これだけは使えるようになってください

1. ポインタって本当に使えないとダメ?

まず結論から• マスターしなくてもだいたい大丈夫です

• ただし「その手の業界」に行く人はマスターしてください

ポインタは何のためにあるか

→ メモリを直接扱うためです

なぜメモリを直接扱う必要が?• 組み込み界隈の人…デバイスの状態の読み書きをメモリアドレスを指定して行います (Memory Mapped IO)

• OS界隈の人…

ソフトウェアが使用するメモリの割り当てを管理する必要があります

• メモリの番地を指定してゴリゴリやる機能が必要

なんでそんなヤバい機能が?ほとんどの人にはいらなくね?→ ググってみましょう

「もともとシステムの記述用に開発された」

(引用元:e-Words)

要するに…

• ポインタは「プログラミングを楽にする」といった理想的な目的で導入されているわけではありません(お察しください)

• 多くの人にとって、ポインタの機能はオーバースペックです

• C言語は決して万人向きではない

何のためにC言語を使うのですか• 極端な話、「ポインタを使うためにC言語を使う」であるべき

• 「C言語はプログラミングの基本だから最初にマスターするべき」的な思想はヤバいと思っています

2. 【部内の】ポインタについて 思うこと【反応】

これは何?

ポインタに関する勘違いのあるあるネタをみんなで共有するコーナーです !

自由に発言してください

よく参考書で見るコード(1)

int x, *p; x = 1; p = &x; *p = 2; printf("x = %d\n", x);

ありがちな反応(1)

「何がうれしいのか分かりません」

よく参考書で見るコード(2)

void swap(int *x, int *y) { int tmp = *x; *x = *y; *y = tmp; }

ありがちな反応(2)

そもそも

void swap(int x, int y) { int tmp = x; x = y; y = tmp;}で動くと思っていたので……

(1)に関して• 例が悪いです

• メリットを感じられなくても、何も問題ありません

(2)に関して• 関数呼び出しとスタックに関する話をする必要があります

• スライド作るのが面倒でした

• ホワイトボードで話をします

考えられる反応

「ぜんぶ参照渡しにしたら良いんじゃないんですか?」 !

→ そういう言語もあります。 最近の主流は「だいたい参照渡し」

3. これだけは使えるようになってください

結局ポインタはどう使えば…• 代表的な利用パターンを4つに分類しました

• この4つが使いこなせれば、基本的に困ることは無いはず

• 使っているうちに、他の場面でも対応できるようになるはず

4つの利用パターン1. 配列or構造体を入力として関数に渡す

2. 配列or構造体を出力として関数に渡す

3. 配列or構造体を入出力として関数に渡す

4. 複数の値を関数から取得

1. 配列or構造体を入力として関数に渡す

// C言語標準ライブラリint puts(const char *s);size_t strlen(const char *s);int strcmp(const char *s1, const char *s2);!// Win32APIATOM RegisterClassEX(const WNDCLASSEX *lpwcx);

2. 配列or構造体を出力として関数に渡す

// C言語標準ライブラリchar *gets(char *s);void memset(void *s, int c, size_t n);void strcpy(char *s1, const char *s2);!// Win32APIBOOL GetWindowRect(HWND hWnd, RECT *lpRect);BOOL GetCursorPos(POINT *lpPOINT);

3. 配列or構造体を入出力として関数に渡す

// C言語標準ライブラリvoid qsort(void *data, size_t num_memb, size_t elem_size, int (*cmp)(const void *, const void *));

4. 複数の値を関数から取得

// C言語標準ライブラリint scanf(...);

演習のお時間です• 問題をいくつか作りました

• 関数を使う問題

• 関数を作る問題

• どのパターンに当てはまるのかも答えてください

演習問題配列の最大値を返す関数int max_element(const int *data, int n);があるとします。!int xs[] = { 1, 1, 4, 5, 1, 4 };の最大値を求める処理を書いてください。

演習問題配列の中に特定の値xがいくつ含まれているか数える関数countを実装してください。!int x = 4;int xs[] = { 1, 1, 4, 5, 1, 4 };int k;!k = count(xs, /* 配列の要素数 = */ 6, x);!みたいに呼び出したいです。

演習問題配列に連番を代入する関数void iota(int *data, int n);があるとします。!int xs[5]; の中身を { 0, 1, 2, 3, 4 }; にしてください。

演習問題配列を特定の値xで埋める関数fillを定義してください。!int x = 72;int xs[10];!fill(xs, /* 配列の要素数 = */ 10, x);!みたいに呼び出したいです。

演習問題渡された文字列に含まれるアルファベットをすべて大文字に変更する関数to_upper_stringを定義してください。!char s[] = "u-hyogo";to_upper_string(s);puts(s); // U-HYOGO!1文字がアルファベットかどうかの判定はint isalpha(int c)アルファベット1文字を大文字に変換するにはint toupper(int c)を使うと便利です。!※isalphaやtoupperはctype.hに含まれています。

演習問題配列の連続する重複要素を消してくれる関数int unique(int *data, int n);があり { 1, 1, 2, 1, 3, 3, 3 } は { 1, 2, 1, 3 } になるとします。戻り値は消した後の要素数です。!int xs[10] = { 1, 1, 1, 2, 3, 3, 3, 3, 4, 4 };の連続する重複要素を消してから消した後の配列を表示する処理を書いてください。

演習問題直交座標で表される点(x,y)を極座標(r,theta)に変換する関数to_polarを実装してください。!引数のデザインはお任せします。偏角はatan(y/x)ではなくatan2(y,x)を使って計算しましょう。

演習問題配列の最大値とそのインデックスを計算する関数int max_argument(const int *data, int n, int *max_value);があるとします。!max_valueにintのポインタを渡すと最大値が代入されます。ただし最大値が不要な場合はNULLを渡せばOKです。!int xs[6] = { 1, 1, 4, 5, 1, 4 };の最大値のインデックスを求める処理を書いてください。

演習問題OpenCVでは画像の色表現を変換する関数cvCvtColorを使ってカラー画像をグレースケール画像に変換します。!void cvCvtColor(const IplImage *src, IplImage *dst, int code);!IplImage *color = cvLoadImage("azunyan.jpg", CV_LOAD_IMAGE_COLOR);IplImage *gray = cvCreateImage(cvGetSize(color), IPL_DEPTH_8U, 1);// グレースケールに変換する処理を書いてください// codeはCV_BGR2GRAYを使います!※実際はメモリを解放する処理が必要です