ページ 11

ポインタ構造体の扱いについて

Posted: 2012年8月20日(月) 05:00
by ナイアガラ
どうもこんにちわ。
ポインタの扱いについて少々手間取っておりまして
質問させていただきます。よろしくお願いします。

ポインタ構造体の初期化ってどうやるのですか。
普通の構造体に対してはmemsetを使いいつも行っているのですが
ポインタがついた構造体についてはよくわかりません。

例えば
#include <stdio.h>

typedef struct {
char name[20];
char sex;
int age;
double height;
double weight;
} person_t;

int main(void)
{

person_t *per;

memset(par , 0x00 , sizeof(*par));

}

以上です。
よろしくお願いします。

Re: ポインタ構造体の扱いについて

Posted: 2012年8月20日(月) 06:08
by box
ナイアガラ さんが書きました:

コード:

      person_t *per;
    
      memset(par , 0x00 , sizeof(*par));
per なのか par なのかわかりませんが、
構造体へのポインターが指す領域をちゃんと定義してから
memset する必要があるような気がします。

それから、memset のプロトタイプ宣言が書いてあるヘッダーを
正しくインクルードする必要もありそうです。

Re: ポインタ構造体の扱いについて

Posted: 2012年8月20日(月) 09:31
by びす
ポインタを定義しただけでは、ポインタの示す先に構造体のメモリが確保されていないからだと思います
Cならmalloc/free、C++ならnew/deleteで動的にメモリを確保しましょう

C

コード:

    person_t *per;

    per = (person_t *)malloc(sizeof(*per)); //メモリ確保

    memset(per, 0x00 , sizeof(*per)); //初期化

    //per使った作業

    free(per); //メモリ解放
C++

コード:

    person_t *per;

    per = new person_t; //メモリ確保

    memset(per, 0x00 , sizeof(*per)); //初期化

    //per使った作業

    delete per; //メモリ解放

Re: ポインタ構造体の扱いについて

Posted: 2012年8月20日(月) 13:54
by beatle
びす さんが書きました:C

コード:

    person_t *per;

    per = (person_t *)malloc(sizeof(*per)); //メモリ確保

    memset(per, 0x00 , sizeof(*per)); //初期化

    //per使った作業

    free(per); //メモリ解放
C++

コード:

    person_t *per;

    per = new person_t; //メモリ確保

    memset(per, 0x00 , sizeof(*per)); //初期化

    //per使った作業

    delete per; //メモリ解放
ソースコードの言語を明示するときは code=Cpp, code=C のように言語名を指定するといいかもしれませんね。

さて、sizeof(*per)でもいいのですがsizeof(person_t)のほうが直感的かと思います。
*ptrだと、ptrを初期化するまえに参照しているように見えちゃいます。

コード:

    person_t *per;

    per = (person_t *)malloc(sizeof(person_t)); //メモリ確保

    memset(per, 0x00 , sizeof(person_t)); //初期化

    //per使った作業

    free(per); //メモリ解放
それから、C++のnewはメモリ領域がその型に合ったやり方で初期化されることが保証されていますから、わざわざmemsetする必要はありません。
newしたものがC非互換のクラスであれば、むしろmemsetしてはいけません。

コード:

    person_t *per;

    per = new person_t; //メモリ確保

    // memset(per, 0x00 , sizeof(*per)); //newで確保した領域はnewにより既に初期化されている

    //per使った作業

    delete per; //メモリ解放

Re: ポインタ構造体の扱いについて

Posted: 2012年8月21日(火) 02:47
by ナイアガラ
boxさん、びすさん、beatleさん、素早い返答、ご教授ありがとうございました!
大変勉強になりました。
試してみたところうまく動き、値も入力してみて表示もしてくれました。
ポインタ構造体は宣言しただけでは領域を確保しただけで実体はまだ生成されていない、という感じでしょうか。
そして変数の大きさで初期化するのではなく、型の大きさでメモリ確保、初期化するのが正解、安心ということですかね。
とりあえずそのように理解しました(違うかもしれませんが。)

もっとポインタについて理解を深めないといけませんね。
ちゃんと理解できればもっとCを上手く扱えるのになあ。
ポインタのポインタとか。ややこしく思えてきてしまうので慣れが必要ですね。
またご教授いただけたら、と思います。
大変助かりました!
本当にありがとうございました!

Re: ポインタ構造体の扱いについて

Posted: 2012年8月21日(火) 06:56
by box
ナイアガラ さんが書きました: ポインタ構造体は宣言しただけでは領域を確保しただけで実体はまだ生成されていない、という感じでしょうか。
ポインター構造体、という用語に違和感があります。
例えば、

コード:

    int *p;
この場合に、pを何と呼ぶのでしょうか。ポインターint、あるいはポインターint型、ですか?
そうじゃないですよね。int型へのポインターです。
これと同じで、ポインター構造体ではなく、構造体へのポインターが正しいと思います。

なお、

コード:

    struct hoge *p;
と「定義」した(宣言じゃないですよ)時点で、構造体へのポインターpの実体は存在しています。
ただし、この定義が関数内のローカル変数であった場合、その値(つまりどこを指しているかってこと)は
ゴミです。何が入っているかわかりません。つまり、どこを指しているかわからないってことです。
ですので、例えば

コード:

    p = (struct hoge *) malloc(10 * sizeof(struct hoge));
のように書いて、pがどこを指しているかを明示する(上の例だと構造体の領域10個分の先頭)
必要があります。