構造体ポインタを使おう
C言語ここまで出来れば大丈夫!という基準は何か?
・とりあえず10,000行
・malloc/free使えりゃOK
・標準ライブラリ以外も使えるようになった
・10行でテトリスを書いた、私はナニカサレタヨウダ
うーん、人によってさまざまでしょう。
私なりの考えとしては、
「構造体ポインタ」を使えるでしょうか。
つまり、OpenCVでよく見る
ちなみに私はcvReleaseImage()の引数がなぜポインタのポインタなのかが未だに理解できません。無駄じゃね?
グローバルな構造体で済む場合もありますが、複数のファイルから構成されるプログラムの場合、extern宣言ばかりになってどこで定義したかわからなくなります。関数に渡すにしても参照渡しの方が効率が良いですし、何より.より->の方がカッコ良いです。
ポインタを「オブジェクトのID」と考える方法はOpen Dynamics Engineを参考にしています。
構造体ポインタはリスト構造を組むときにも使えるので便利なテクニックです。
まぁ、一番いいのは他の人にも読みやすいコードが書けることですけどね!
・とりあえず10,000行
・malloc/free使えりゃOK
・標準ライブラリ以外も使えるようになった
・10行でテトリスを書いた、私はナニカサレタヨウダ
うーん、人によってさまざまでしょう。
私なりの考えとしては、
「構造体ポインタ」を使えるでしょうか。
つまり、OpenCVでよく見る
のような仕組みを理解できたらOK!ってことです。
// オブジェクトの確保
IplImage *img = cvCreateImage(...);
// 操作
cvThreshold(img, ...);
// 解放
cvReleaseImage(&img);
ちなみに私はcvReleaseImage()の引数がなぜポインタのポインタなのかが未だに理解できません。無駄じゃね?
グローバルな構造体で済む場合もありますが、複数のファイルから構成されるプログラムの場合、extern宣言ばかりになってどこで定義したかわからなくなります。関数に渡すにしても参照渡しの方が効率が良いですし、何より.より->の方がカッコ良いです。
10行目でImageIDにtypedefしているのがミソです。
#include <stdio.h>
#include <stdlib.h>
/* 画像データ */
struct IMAGE {
int width;
int height;
unsigned char *data;
};
typedef struct IMAGE *ImageID;
/* 画像オブジェクトの生成 */
ImageID createImage(int img_width, int img_height);
/* 画像の2値化 */
void binalizeImage(ImageID img, int lower, int upper);
/* 画像の解放 */
void releaseImage(ImageID img);
ポインタを「オブジェクトのID」と考える方法はOpen Dynamics Engineを参考にしています。
上の例のように、実体はmallocで確保して、ユーザにはポインタだけ渡してやります。ポインタで管理する利点は「オブジェクトの確保に失敗したらヌルポインタを返す」とすれば、そのオブジェクトが存在しているか否かがわかることです。
#include "image.h"
/* 画像オブジェクトの生成 */
ImageID createImage(int width, int height)
{
ImageID img = (ImageID)malloc(sizeof(struct IMAGE));
if (!img) return 0;
/* 内部データ */
img->width = width;
img->height = height;
img->data = (unsigned char*)malloc(img->width * img->height * sizeof(unsigned char));
if (!img->data) {
free(img);
return 0;
}
return img;
}
/* 画像の2値化 */
void binalizeImage(ImageID img, int lower, int upper)
{
if (!img) return;
/* 閾値以内なら255 */
for (int i = 0; i < img->width*img->height; i++) {
if (lower < img->data[i] && img->data[i] < upper) img->data[i] = 255;
}
}
/* 画像の解放 */
void releaseImage(ImageID img)
{
if (img) {
free(img->data);
free(img);
img = 0;
}
}
いやぁ、プログラミングって奥が深いですね!
#include "image.h"
int main(int argc, char **argv)
{
/* 画像の生成 */
ImageID img = createImage(320, 240);
/* 2値化 */
binalizeImage(img, 127, 255);
/* 解放 */
releaseImage(img);
return 0;
}
構造体ポインタはリスト構造を組むときにも使えるので便利なテクニックです。
まぁ、一番いいのは他の人にも読みやすいコードが書けることですけどね!
スポンサーサイト