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

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

新規登録して質問してみよう
ただいま回答率
87.20%
C

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

structure

このタグは、プログラム言語におけるデータ型structure(構造体)に関するタグです。

解決済

C言語の構造体を、メンバ変数の指定なしでPrintfする際の、挙動について

_fox
_fox

総合スコア15

C

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

structure

このタグは、プログラム言語におけるデータ型structure(構造体)に関するタグです。

5回答

0評価

1クリップ

801閲覧

投稿2022/03/09 15:34

編集2022/03/12 14:08

こんにちは。C言語の構造体について質問があります。
下記のようなコードを書いて構造体の動作を確認しています。
疑問点は、コードの下から3行目と4行目の内容です。

構造体の実体をPrintfしたら、構造体の先頭にあるメンバ変数の値だけが出力されると思っていたら、
メンバ変数が全て出力できました。

この動きがよくわからないのですが、
構造体の中身を出力しようとしたときに、
具体的なメンバ変数を指定しない場合は、全てのメンバ変数の値が出力される仕様になっているという事なのでしょうか?

もしどなたか詳しい方がいらっしゃいましたら、教えていただけますと幸いです。

C

#include <stdio.h> struct animal { /* data */ int eye; double weight; }; int main(void){ struct animal animal = {0}; struct animal *panimal = &animal; panimal->eye=11; //構造体animalの実体のメンバ変数eyeにアクセスしています //全部11が出力されます printf("%d\n",panimal->eye); printf("%d\n",animal.eye); printf("%d\n",(*panimal).eye); //構造体animalの実体のメンバ変数eyeのアドレスを表示しています   //全部同じアドレスが出力されます printf("%p\n",panimal); printf("%p\n",&(panimal->eye)); printf("%p\n",&animal); printf("%p\n",&animal.eye);  //↑ここまでは想定していた動きでした。    //↓これら2つが何が起きているのか分かりません…… printf("%d,%f\n",*panimal); //←*panimalはアドレス&animalが指す値なので、メンバ変数eyesの値だけが出力されるはずではないですか? //しかし実際は、-Wformatオプションでビルドするとワーニングが出るものの、なぜかメンバ変数が2つとも読めました。理由がわかりません。 printf("%d,%f\n",animal); //←もしかしてこれも行けるかもと思って書いてみました、これもメンバ変数が2つとも読めて、何が起きているのかわかりません。 return 0; }

追記します。
構造体を配列として宣言して使った場合、メンバ変数を指定せずにPrintfすることはできませんでした。

C

#include <stdio.h> //構造体の型宣言 struct student{ int no; // 学籍番号 char name[256]; // 氏名 int year; // 学年 char s_class[256]; // クラス }; int main(void){ int i; //構造体の宣言と初期化の代入 struct student students[4] = { {1, "nakano", 1, "c"}, {2, "ooisi", 2, "b"}, {3, "okamoto", 1, "a"}, {4, "minabe", 2, "a"}, }; for(i = 0; i < 4; i++) { //結果の出力       //コメントアウトしているコレは意図通りに要素を表示してくれます↓ //printf("%d,%s,%d,%s\n", students[i].no, students[i].name, students[i].year, students[i].s_class);             //↓これは同じようにワーニングが出るのですが、実行してもデータは取れませんでした。    printf("%d,%s,%d,%s\n",students[i]); } return 0;

更に追記します。
jimbeさんにコメントいただいて、

仮に配列みたいにスタックしていて、本来はエラー吐きそうな実装だけれども、たまたまうまくいっているだけと考えると、
ポインタをインクリメントしたり、糖衣構文じゃない配列の値出力の書き方でデータが読み出せるんじゃないかと思って、

C

//ポインタをインクリメントするパターン printf("--%d\n",*(&animal+0)); printf("--%f\n",*(&animal+1)); //糖衣構文じゃない配列の書き方 printf("%d\n",0[&animal]); printf("%f\n",1[&animal]);

こんな文を追記してみたところ、私の環境では、両方とも11と0.0が出力されました!(びっくり!)
確かにこれが動いたということは、スタックフレームで実現されているのかもしれませんね。

更に配列と同じ書き方もしてみましたが、さすがにこちらはエラーが出力されました。

C

 //これは動かない printf("%d\n",&animal[0]); printf("%f\n",&animal[1]);

初心者なものでちょっと不安なのですが、
基本的には、「C言語の構造体を、メンバ変数の指定なしでPrintfしたりしない。Printfするときは必ずメンバ変数を指定する」という風に覚えておけばいいんですかね?

それとも、日常的にprintf("%d,%f\n",animal);的な、メンバ変数を指定しない出力する文を書いたりされますか?

良い質問の評価を上げる

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

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

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

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

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

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

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

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

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

まだ回答がついていません

会員登録して回答してみよう

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

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

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

C

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

structure

このタグは、プログラム言語におけるデータ型structure(構造体)に関するタグです。