ページ 11

構造体を指すポインタについての質問です。

Posted: 2015年4月10日(金) 18:46
by 本間
構造体を指すポインタについての質問です。

先日、関数で渡された構造体へのポインタでつまづくことがありまして、なんとかそのプログラムミスは直したのですが、
構造体へのポインタpに対して、*p, &p, pそれぞれは何を指すのだろうかと思い、
*p = ?
&p = ?
p = pの指す構造体のアドレス
ではないかと予想をし(二つは埋まってませんが...)、下のプログラムを作りました。

そして実行結果をみて、
*pについては、その構造体のメンバの一番先頭の変数の値を、
pについては、予想通り構造体のアドレス(別のやつかも知れませんが...)を、それぞれ表示する。ということなのだろうと思いましたが、
&pについては、書記化指定子を%dや%pにしてみましたが、*pでもpでもない値が表示されました。

&pとは一体なにを指すのでしょう?

コード:

#include<stdio.h>

typedef struct{
    int n;
    double a;
}test_t;

void hyouji( test_t *test, int t, double d){
    test->n = t;
    test->a = d;
    printf("*test = %d\n", *test);
    printf("test  = %p\n", test);
    printf("&test = %p\n", &test);
    printf("&test = %d\n", &test);
    
}

test_t m_test;

int main(void){

   hyouji(&m_test, 3, 2.5);
   
    return 0;
}

Re: 構造体を指すポインタについての質問です。

Posted: 2015年4月10日(金) 19:14
by usao
>構造体を指すポインタについての質問

という時点で,何か話がおかしい雰囲気を感じます.

int a;
int *p = &a;
としたときの p, *p, &p と意味的に何ら変わらないと思うのですが.

Re: 構造体を指すポインタについての質問です。

Posted: 2015年4月10日(金) 19:30
by 本間
>>usaoさん


p, *pは、pは指すもののアドレスを、*pは実体を指す、と習いました。そしてよくみかけます。
しかし、ポインタに対してアドレス演算子&をつけて&pとしたらどうなるのかというのは知らず、長年疑問でした。
冒頭で申しましたプログラムミスは、仮引数に構造体へのポインタを持つ関数内で、ある別の関数にその構造体のアドレスを渡そうとしたところ、
pと渡すはずだったのですが、間違えて&pで渡したところから始まりました。
なので、そこをpに直したら直ったのですが、なぜ&pではいけないのか分からず、まずは&pは何を指すかを調べようと思い、質問をさせていただきました。

>>int a;
int *p = &a;
としたときの p, *p, &p と意味的に何ら変わらないと思うのですが.

pと*pは指すものはちがうのではないでしょうか?意味を取り違えていたらすみません。
それとも宣言したときにint *p=&aとするのと宣言した後にp=&aとやるのは同じ、という意味でしょうか?

Re: 構造体を指すポインタについての質問です。

Posted: 2015年4月10日(金) 19:36
by みけCAT
C言語では、*pはそのポインタが指す構造体データを、&pはそのポインタのデータが格納されているアドレスを表します。

コード:

#include <stdio.h>

typedef struct {
  int x;
  double y;
} s;

int main(void) {
  s a;
  s* b=&a;
  printf("%u\n",(unsigned int)sizeof(*b));
  printf("%u\n",(unsigned int)sizeof(a.x));
  return 0;
}

Re: 構造体を指すポインタについての質問です。

Posted: 2015年4月10日(金) 19:58
by 本間
>>みけCATさん

返信遅れてしまいすみません。載せてくださったコードを使わせていただき、あれこれ試行錯誤しておりました。
&pはポインタのデータが格納されているアドレスを指す、とおっしゃられましたが、ということはここでいう&pすなわち&bは実体の無いものなのかと思い、

コード:

printf("%u\n",(unsigned int)sizeof(a.x));
この部分のa.xのところを&bにしてみたのですが、きまって4と表示されました。
なぜなのでしょう?
質問ばかりですみません

Re: 構造体を指すポインタについての質問です。

Posted: 2015年4月10日(金) 20:07
by usao
int a; に対する &a が int型変数aのアドレス であることと
int *p; に対する &p が int*型変数pのアドレス であることに差は無いように思うのですが.


>そこをpに直したら直ったのですが、なぜ&pではいけないのか分からず

単純に引数の型が異なるからではないでしょうか.

コード:

//何か構造体があって…
struct S{ ... };
//こういう関数がある
void func( struct S * )  //引数は S*型
{ ... }

int main()
{
  struct S obj;  //objはS型
  struct S *pS = &obj;  //pSは S*型

  func( pS );  //引数の型と一致しているからOK
  func( &pS );  //&pS だと S**型になるから,引数の型と一致せずエラー
  ...
}

>pと*pは指すものはちがうのではないでしょうか?意味を取り違えていたらすみません。
>それとも宣言したときにint *p=&aとするのと宣言した後にp=&aとやるのは同じ、という意味でしょうか?

ひょっとして

コード:

int a;
int* p = &a;
と書いたらわかりやすかったりしますか.

Re: 構造体を指すポインタについての質問です。

Posted: 2015年4月10日(金) 20:37
by みけCAT
本間 さんが書きました:&pはポインタのデータが格納されているアドレスを指す、とおっしゃられましたが、ということはここでいう&pすなわち&bは実体の無いものなのかと思い
実体はあります。

コード:

#include <stdio.h>

typedef struct {
    int a;
    double b;
} s;

void hoge(s** ptr) {
    static s hoge;
    printf("ptr = %p\n", (void*)ptr);
    hoge.a = 346;
    hoge.b = 3.142857;
    *ptr = &hoge;
}

int main(void) {
    s fuga;
    s* p = &fuga;
    fuga.a = 573;
    fuga.b = 2.71828;
    printf("&p = %p\n", (void*)(&p));
    hoge(&p);
    printf("%d\n", (*p).a);
    printf("%f\n", (*p).b);
    return 0;
}
本間 さんが書きました:

コード:

printf("%u\n",(unsigned int)sizeof(a.x));
この部分のa.xのところを&bにしてみたのですが、きまって4と表示されました。
なぜなのでしょう?
本間さんが使っている環境のポインタの大きさが4バイト(char型の大きさの4倍)だからでしょう。

Re: 構造体を指すポインタについての質問です。

Posted: 2015年4月10日(金) 20:39
by みけCAT
本間 さんが書きました:pと*pは指すものはちがうのではないでしょうか?意味を取り違えていたらすみません。
それとも宣言したときにint *p=&aとするのと宣言した後にp=&aとやるのは同じ、という意味でしょうか?
ポインタ型の宣言に使う*と、間接演算子の*を勘違いしていませんか?

Re: 構造体を指すポインタについての質問です。

Posted: 2015年4月10日(金) 20:47
by 本間
>>usaoさん

なるほど、ありがとうございます。引数の型が違う、という風に考えればすべて納得いきました。
あと、それとも宣言したときにint *p=&aとするのと宣言した後にp=&aとやるのは同じ、という意味でしょうか?
のところは無視してください。自分でもなんでこんな事を言ったのか意味がわかりません。

Re: 構造体を指すポインタについての質問です。

Posted: 2015年4月10日(金) 20:52
by 本間
>>みけCATさん

なるほど、格納されているアドレスを指すポインタの大きさのことだったのですね。ありがとうございます。
それとも宣言したときにint *p=&aとするのと宣言した後にp=&aとやるのは同じ、という意味でしょうか?のところはわすれてください...

>>ポインタ型の宣言に使う*と、間接演算子の*を勘違いしていませんか?

ポインタ型宣言に使う*は単純に宣言するものがポインターであるのを示すために、
間接演算子*はポインタが指すオブジェクトへアクセスするものである、と自分は理解しておりますが、何か間違った解釈はしておりますでしょうか?

Re: 構造体を指すポインタについての質問です。

Posted: 2015年4月10日(金) 22:25
by 本間
おふたりとも本当にありがとうございました。
これからもC言語に精進いたします。

Re: 構造体を指すポインタについての質問です。

Posted: 2015年4月10日(金) 22:38
by みけCAT
本間 さんが書きました:ポインタ型宣言に使う*は単純に宣言するものがポインターであるのを示すために、
間接演算子*はポインタが指すオブジェクトへアクセスするものである、と自分は理解しておりますが、何か間違った解釈はしておりますでしょうか?
C言語では正しいと思います。