質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.49%

  • C

    3809questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    3581questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

【C言語】&構造体ポインタ変数名->要素名 と 構造体ポインタ変数名.要素名 の違い

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 889

yuki1013

score 1

困っていること(1)

使っている参考書は『苦しんで覚えるC言語』です。16章まで勉強を進めていて3週間経過しています。
(C言語が初めて扱う言語のため、本当にプログラム初心者です。)
C言語の書式について疑問が生じました。

ポインタ変数にはアドレスを入力出来るモードと
数値をメモリに記憶出来るモードがあることは理解できたのですが
構造体の勉強中に混乱し始めてしまって…。
困っていること(2)が本題です。

しかし簡単なところから確認していきたいので、お付き合い願います。
まず、以下の15行目の書き方には問題がありますか?
ポインタ変数なので、まずは[*data]として通常の変数を記憶できるようにしました。
scanf関数を用いているので[&*data]としています。

ソースコード

#include <stdio.h>

void test(int *data); /*プロトタイプ宣言*/

int main(void)
{
    int hoge;
    test(&hoge); /*hogeのアドレスをtest関数に与える*/
    printf("hoge = %d\n",hoge);
    return 0;
}

void test(int *data) /*hogeのアドレスを受け取る*/
{
    scanf("%d",&*data); /* 15行目 */
    return 0;
}

困っていること(2)

今度は構造体で、構造体ポインタ変数を用いるときに疑問が生じてしまいました。

(*構造体ポインタ変数名).要素名

構造体ポインタ変数名->要素名
と書き改めることまでは把握できました。

以下の32行目の書き方で混乱してしまいました。
&data->release

&(*data).release
↓ (?)
data.release
では「struct or union」と表示されるのですが何が問題なのでしょうか…。
上記の一段目と二段目は同じですが、三段目とこれらの違いがはっきりしていなくて悩んでいます。

ソースコード

#include <stdio.h>

/*新規に game型 を宣言*/
typedef struct {
    char name[256];        /*作品名*/
    int release;        /*発売年*/
    char genre[256];    /*ジャンル*/
} game;

void Input_game(game *data);
void Output_game(game data);

int main(void)
{
    int i;
    game data[5];

    for (i = 0;i < 5;i ++) {
        Input_game(&data[i]);
    }

    for (i = 0;i < 5;i ++) {
        Output_game(data[i]);
    }

    return 0;
}

void Input_game(game *data)
{
    scanf("%s",data->name); /* nameが配列名なので、&は必要ない 。*/
    scanf("%d",&data->release); /* releaseが変数名なので&をつける…?*/ /*32行目*/
    scanf("%s",data->genre); /* nameと同様 */
    return 0;
}

void Output_game(game data)
{
    printf("作品名:%s 発売年:%d ジャンル:%s\n",data.name,data.release,data.genre);
    return 0;
}

追加の質問

「苦しんで覚えるC言語」の次に読んでみると、参考になるかもしれない書籍がありましたら
教えていただきたいです。
(こちらは本当におまけですので、無理に答えていただなくても大丈夫です。)

よろしくお願いします…!

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+5

(1)はすでにアドレスですので、dataのままいいです。&*dataはdataが示す値を取得して、その値が存在する場所のアドレス(結局はdataそのもの)になるため、意味が無い演算です。よくscanf&を付けるのはポインタを指定しなければならないからで、既にポインタの場合はそのままでかみません。

(2)で注意すべきなのは演算子の優先順位とその優先順位が高いところから値を求めていく点です。演算子の優先順位は下記を参考にしてください。
Wikipedia:CとC++演算子#演算子の優先順位
上からわかるように&->->の方が結合が強いため、先に計算されます。わかりやすく()をつけると

&data->release

&(data->release)

&((*data).release)

となります。つまり、上記の動作は()の内側から計算されるため、

  1. dataが示す先の構造体を得る *data
  2. 1.の構造体の中のreleseを得る (*data).relese
  3. 2.で得た値が存在する場所のアドレスを得る &((*data).relese)

という動作になります。

(おまけ)古典ですが聖典「K&R」は一度は読んでおくと良いかもしれません。内容は古いですが、C言語を作った開発者によるC言語のエッセンスが詰まっています。ただ、全く初心者向けではないため、一度読んだだけで全て理解するのは難しいです。ある程度やってから再度読み直すと、その素晴らしさに気付くことでしょう。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/31 13:40

    (1)の内容は、説明していただけるとそうだった! と頷けるのですが、自力ではなかなか気づけませんでした…
    「`&*data`ではdataが示す値を取得して、その値が存在する場所のアドレス(結局はdataそのもの)になるため…」
    この部分が順を追って解説していたため、非常に参考になりました!

    (2)の内容は、今まで読んできた範囲では、ほとんど優先順位について触れていなかったのでためになりました。
    さらに優先順位を意識して考え直してみると、* よりも . が優先されてしまうので
    `(*data).release`…そのあとにアドレスを得るための&… ようやく分かりました!
    疑問が解消したので次の章に進むことが出来そうです、ありがとうございます!

    キャンセル

+1

ポインターってわかりにくいですよねー
今一度おさらいしてみましょうよ
なお,長いですが,直接的な回答になっているわけじゃないのであしからず,です.

int a;
a = 1;


これで 変数a に 1が入るのはわかると思いますが,このとき,aというのはメモリにaという名前のついたある大きさの領域が確保されています.

ポインターを勉強すると * やら & を使ってアドレスを演算,それに向かって代入する事ができる,という話に出逢います.なるほど,じゃあ

int *a;
*a = 1;


なんてやっても出来そうですね.

ダメでした…

これは何故かと言うと int *a が aという名前のアドレスを記憶する型 の変数だからです.
ですのでその変数に数値の1をしまうということは直接的には出来ません(これがメモリのアドレスを示す値とわかっている(明示する)なら別ですが,上のコードの互換と考えて読んで下さい).

int *a; // aというポインタ変数
int b;  // bというint型変数
a = &b;  // aはbというint型変数の場所(アドレス)を記憶
*a = 1;  // bに1を代入
printf("aでアクセスするなら -> %d\n", *a);
printf("bでアクセスするなら -> %d\n", b);


ああ,もうなんでしょう! * やら & やらごちゃごちゃしますねー.
でも,これで変数bに1が入ったのがわかりますかね?
それが変数aでもアクセス出来ているのが分かりますか?

このあたりを今一度しっかり(もしくはしっくりくるまで)理解しますと,その先がとても楽になります.

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/31 11:58

    自作関数の(仮ポインタ引数)に、引数のアドレスを渡したときは
    *をつけて通常の変数のように数値を代入出来ることに慣れてしまっていたために
    一瞬、上二つの違いを整理できませんでした。
    アドレスを記憶していないから、この二段目の場合はポインタ変数に数値を代入できないのでしたね。

    完全に理解できたと言い張れるほどではないですが、この二つを見比べてつっかえていたものが解消したような気がしましたっ。
    ありがとうございますっ!

    キャンセル

関連した質問

  • 解決済

    構造体の理解が足りません

    前提・実現したいこと ゲームのパラメータ入力画面みたいなものを作っているのですが 一定以上のパラメータが入力されたら警告文を出す というところで躓いています。 自分ではいろ

  • 解決済

    Cで行列のランク計算のプログラムを作っています。

    前提・実現したいこと Cで行列のランク計算をするプログラムを作っています。 プログラムの流れは、 1.行列の行数(lnum)、列数(cnum)を入力 2.行列の各成分を

  • 解決済

    C言語のエラー修正について

    コード #include <stdio.h> #define New (element) RealNew( & element ) #define InputInt( number

  • 解決済

    打ち込んだ数値をすぐに表示したい。

    今一度お願いいたします。 void pos_training(void)の /* ブロックを選択させる */ do { printf("番号(練習中止は99)

  • 解決済

    c言語 リスト構造について...

    前提・実現したいこと 最近C言語でリスト構造を勉強したので自己流でリスト構造のプログラムを作成したのですが正常に作動しません。どなたか解決法を教えてください。 説明不足だったの

  • 受付中

    リスト構造と待ち行列

    リスト構造と待ち行列をしたいのですが、よくわかりません。 おすすめのサイトや説明おねがいします。 #include <stdio.h> #include <stdlib.h>

  • 解決済

    c言語 入門レベル問題

    a,b 入力したら、b、a 逆の順番に出てたいです、 下記プログラミング7,8入力したら、a = 0, b = 7 出てしまいました。 不備なところ教えていただけますか。 #i

  • 解決済

    構造体とポインタと配列がごっちゃになって困っています。

    下記のプログラムのどこがどうダメなのか教えてください。 1.関数の引数に通常の変数を渡すと値渡しとなり、 呼び出し元の変数に変更を加えることができませんが、 関数の引数に配列を

同じタグがついた質問を見る

  • C

    3809questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • C++

    3581questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。