🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

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

Q&A

解決済

6回答

458閲覧

構造体とポインタについて

os-t

総合スコア20

C

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

0グッド

0クリップ

投稿2019/12/21 14:06

前提・実現したいこと

構造体を用いて、氏名と身長・体重を順に表示したい。

発生している問題・エラーメッセージ

invalid initializer PHYSICAL *pdata[3] = &data[3];

該当のソースコード

C言語

1#include <stdio.h> 2#include <math.h> 3 4typedef struct physical { 5 char name[64]; 6 float height; 7 float weight; 8} PHYSICAL; 9 10int 11main(void) 12{ 13 int i; 14 15 PHYSICAL data[] = { 16 {"Yamada 0taro", 168.9, 61.8}, 17 {"Yamada 1taro", 163.6, 70.1}, 18 {"Yamada 2taro", 177.8, 58.7} 19 20 21 }; 22 PHYSICAL *pdata[3] = &data[3]; 23 24 25 for (i = 0; i < sizeof data / sizeof data[0]; i++) { 26 printf("%s %e %e\n", pdata[i]->name, pdata[i]->weight, pdata[i]->height); 27 } 28 return 0; 29}

試したこと

エラーメッセージの箇所をどのように変更すればよいかわかりません。

補足情報(FW/ツールのバージョンなど)

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答6

0

pdataは大きさ3の配列なので、

C

1PHYSICAL *pdata[3] = {なにか, なにか, なにか};

のように初期化します。1-2個しか書かないときは残りには0が入ります。

何を入れたいのか不明ですが、例えば、

C

1 PHYSICAL *pdata[3] = {&data[0],&data[1],&data[2]};

ただ、これだとわざわざpdataを作る意味が無いですが。

投稿2019/12/21 14:17

otn

総合スコア85882

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

os-t

2019/12/21 14:23

PHYSICAL *pdata[3] = {&data[0],&data[1],&data[2]};の部分をfor文で書くことは可能でしょうか
otn

2019/12/21 14:26

初期化構文じゃなくて、普通に代入文で代入すればいいです。
os-t

2019/12/21 14:35

投稿するためにデータの数を減らしました。今自分が実行しようとしているデータは100個のデータがあるのでなるべく手間を省こう思ったのですが、代入していくしか方法はないのでしょうか・・・ pdataを用いているのは、後々にひとりずつのBMIから全員の平均BMIを求める関数と全員の身長と体重の測定値の標本平均と標準偏差の推定値を求める関数を定義しmain 関数内で呼び出して使うためです。
otn

2019/12/21 14:56

> 代入していくしか方法はないのでしょうか・・・ forを使ってループにすればいいのでは? というか、 > pdataを用いているのは、 dataをそのまま使えない理由が、質問のコードからは不明です。
guest

0

もう回答は出揃っているようですし「pdata要らないよ」が正答な気がしますが
ソースコードを見る限り「ポインタの扱いが分からないまま雰囲気で書いた」感が強いのでポインタの扱いについて1つ。

C

1PHYSICAL *pdata[3];

と書いた場合これは「PHYSICALのポインタ型の要素を持つ長さ3の配列」を意味します。
つまり各要素はPHYSICAL*になります。
対して

C

1&data[3];

は「dataの4番目の要素のポインタ」の意味になります。元々dataは長さ3なのではみ出ていますし、
仮に配列dataの先頭要素のポインタを取得したい場合は単にdataもしくは&data[0]になります。

つまりもしpdataを使うのであれば

C

1PHYSICAL *pdata = data;

が正解ですが今回の場合全く必要がありません。
ちなみにこれはポインタを代入しているだけなので中身は複製されていません(同じものを見ている)

ポインタの概念は難解かもしれませんが、重要なので一度きっちり理解しておくと後々のために良いかと思います。

投稿2019/12/22 03:47

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

Cでは、「配列」はデータが密に並んだデータ構造です。data[N]とdata[N+1]は必ずお隣さん同士なので、data[N]の場所がわかればdata[N+1]の場所もわかる...つまりdata[0]の場所さえ知っていれば、任意のdata[N]は計算でわかるでしょ、だから配列を扱うときは先頭要素へのポインタだけ受け渡しすれば最低なんとかなるよね! と割り切ってしまったのがCの配列の扱いの原則です。(ただし、その割り切りの結果配列を関数に渡すとサイズの情報は失われますから、必要なら別途渡す必要はあります。)

つまり、単純にN個のデータを関数に渡してごにょごにょするための施策としては、PHYSICAL *pdata[3]のようなものを設ける意味は全くありません。

ひとりずつのBMIから全員の平均BMIを求める関数と全員の身長と体重の測定値の標本平均と標準偏差の推定値を求める関数を定義し

というのが本来の目的であったなら、

C

1#include <stdio.h> 2 3typedef struct physical { 4 char name[64]; 5 float height; 6 float weight; 7} PHYSICAL; 8 9void printData(PHYSICAL dt[], size_t sz) {//本番ではBMI計算してどーたら、して下さい 10 for (int i = 0; i < sz; i++) { 11 printf("%s %e %e\n", dt[i].name, dt[i].weight, dt[i].height); 12 } 13} 14 15int main(void) { 16 PHYSICAL data[] = {{"Yamada 0taro", 168.9, 61.8}, 17 {"Yamada 1taro", 163.6, 70.1}, 18 {"Yamada 2taro", 177.8, 58.7}}; 19// 配列を単独で記述したら配列の先頭要素へのポインタと解釈される 20// 配列を引数に渡すと、ポインタと解釈されるので要素数の情報は別途渡さないといけない 21// 要は、これで配列の情報が全て関数に伝えられるということ 22 printData(data, sizeof data / sizeof data[0]); 23 return 0; 24}

このようなことがあなたがやるべきことじゃないでしょうか。

PHYSICAL *を導入しなきゃと考えてしまったところで道を誤ったと思います。まぁ、この段階でいろいろ歩き回ってみるのはいい勉強になるでしょうから、「誤った」といっても必ずしも悪いことじゃありませんね。

PHYSICAL *を導入したらどういうことが出来るかと言うと、例えば元の配列をいじらずに順番の変更が出来ます(ソートしたりとか)。こんなプログラムなら、PHYSICAL *が有効に使えるでしょう。

C

1#include <math.h> 2#include <stdio.h> 3 4typedef struct physical { 5 char name[64]; 6 float height; 7 float weight; 8} PHYSICAL; 9 10int main(void) { 11 int i; 12 13 PHYSICAL data[] = {{"Yamada 0taro", 168.9, 61.8}, 14 {"Yamada 1taro", 163.6, 70.1}, 15 {"Yamada 2taro", 177.8, 58.7} 16 17 }; 18 PHYSICAL *pdata[sizeof data / sizeof data[0]]; // sizeof演算子はコンパイル時に静的に値が決まっているのでVLA扱いにならない 19 for (i = 0; i < sizeof data / sizeof data[0]; i++) {//いわゆる初期化 20 pdata[i] = &data[i]; 21 } 22 //最初の状態を表示 23 for (i = 0; i < sizeof data / sizeof data[0]; i++) { 24 printf("%s %e %e\n", pdata[i]->name, pdata[i]->weight, pdata[i]->height); 25 } 26 printf("\n"); 27 //データを入れ替えてみる 28 PHYSICAL *tmp = pdata[1]; 29 pdata[1] = pdata[0]; 30 pdata[0] = tmp; 31 //入れ替えたものを表示 32 for (i = 0; i < sizeof data / sizeof data[0]; i++) { 33 printf("%s %e %e\n", pdata[i]->name, pdata[i]->weight, pdata[i]->height); 34 } 35 printf("\n"); 36 //元データは変更されていない 37 for (i = 0; i < sizeof data / sizeof data[0]; i++) { 38 printf("%s %e %e\n", data[i].name, data[i].weight, data[i].height); 39 } 40 printf("\n"); 41 42 return 0; 43}

投稿2019/12/22 01:22

thkana

総合スコア7703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

os-t

2019/12/22 01:47

ありがとうございます。頑張ってみようと思います。
guest

0

配列名がポインタになるので、関数にそれを渡せます。

C

1#include <stdio.h> 2#include <math.h> 3 4typedef struct physical { 5 char name[64]; 6 float height; 7 float weight; 8} PHYSICAL; 9 10void print(const PHYSICAL *pdata, int n) 11{ 12#if 1 // #if 0 にすると、#else のコードになります。 13 for (int i = 0; i < n; i++) 14 printf("%s %e %e\n", 15 pdata[i].name, pdata[i].weight, pdata[i].height); 16#else 17 for (int i = 0; i < n; i++, pdata++) 18 printf("%s %e %e\n", 19 pdata->name, pdata->weight, pdata->height); 20#endif 21} 22 23int main(void) 24{ 25 PHYSICAL data[] = { 26 {"Yamada 0taro", 168.9, 61.8}, 27 {"Yamada 1taro", 163.6, 70.1}, 28 {"Yamada 2taro", 177.8, 58.7}, 29 }; 30 print(data, sizeof data / sizeof data[0]); 31 return 0; 32}

投稿2019/12/21 17:04

kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

PHYSICAL *pdata[3] = &data[3];

この文が意味不明です
pdataはポインタの配列ですが、右辺の初期化式は配列になってません

投稿2019/12/21 14:23

編集2019/12/21 14:24
y_waiwai

総合スコア88038

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

os-t

2019/12/21 14:49

実際は100個のデータを使うのですが、どのようにすればポインタに渡すことが出来ますか?
y_waiwai

2019/12/21 14:53

初期化式でやろうとせず、実行文で100個代入しましょう。 forループでもやれば一発ですぜ
os-t

2019/12/21 14:55

ありがとうございます
y_waiwai

2019/12/21 15:05

そもそも PHYSICAL *pdata = data; ... pdata[99]=なんたらかんたら; としたい、というはなしでしょうか? またこれは違う、といわれそーですがw そもそもなにをするためにそれをしたいんでしょうか
os-t

2019/12/21 15:23

{"Yamada 0taro", 168.9, 61.8},のようなデータが100個あるという事です。 各個人bmiの平均を出す関数を定義し、その中で使うためポインタに渡そうと考えています。
y_waiwai

2019/12/21 22:47

ポインタを定義したいってことなら、 PHYSICAL *pdata = data; でいけませんか
guest

0

エラーから、初期化の必要がありそうですね。

C

1struct PHYSICAL data[3] = { 2 {"Yamada 0taro", 168.9, 61.8}, 3 {"Yamada 1taro", 163.6, 70.1}, 4 {"Yamada 2taro", 177.8, 58.7} 5};

投稿2019/12/21 14:13

madone99

総合スコア1857

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問