dポイントプレゼントキャンペーン実施中!

関数に構造体を渡したいのですが、エラーが出て上手くいきません。
下のプログラムのように組んでいるのですが、どこが問題なのかご教授願いたいです。
もし、下記のプログラムのようなことができないのでしたら、代替案を提示してもらえると助かります。
環境はVC++です。よろしくお願いします。

struct DATA{
int x;
char name[32];
};

void info(DATA *status[]);

int main(void){
DATA student[3] = {
{ 1, "佐藤" },
{ 2, "高橋" },
{ 3, "田中" },
};
info(&student[]);
return 0;
}

void info(DATA *status[]){
for (int i = 0; i < 3; i++){
printf("%d\n%s", status[i]->x, status[i]->name);
}
}

A 回答 (4件)

お礼への返信です。



> VC++ってCもC++も対応していませんでしたっけ?

対応しているというのは混ぜて書けるという意味ではないですよね。
例えば、GNU Compiler Collection (gcc)は C、C++だけでなくFortran、Java、Adaなんかにも対応していますが、ソースファイルに特殊な命令などを書かず、混ぜて書くことはできません。

あと、C言語とC++は文法がたまたま似ているだけの全く別の言語だと思ったほうがよいです。C言語で自然な書き方とC++で自然な書き方は全く異なります。

C++で書くとしたら、例えばこう書くのではないでしょうか。(C++11に対応していないコンパイラーではコンパイルできません)
#include<vector>
#include<iostream>

using std::vector;

struct DATA{
int x;
char name[32];
};

void info(const vector<DATA>& students);

int main(void){
vector<DATA> students = {
{ 1, "a" },
{ 2, "b" },
{ 3, "c" },
};
info(students);
return 0;
}

void info(const vector<DATA>& students){
for (const auto& student : students) {
std::cout << student.x << " " << student.name << std::endl;
}
}


> この書き方ならポインタ宣言の*は書く必要はなく、
> 関数にアドレスが渡っているということですか?

info関数の中身を見る限り全く必要ありません。C言語でvoid info(struct DATA status[])とvoid info(struct DATA *status)とは同じ意味になります。配列変数は配列の先頭要素のアドレスが格納されていますので、それを引数に渡すということはアドレスを渡すということです。また、配列を受け取るということは、配列の先頭要素のアドレスを受け取るということです。

質問者のように書いたらどういう意味になると思いますか?struct DATAの配列へのポインターを受け取るわけですので、2次元配列を受け取ることになってますが、それは意図通りなのでしょうか?

配列変数は配列の先頭の要素のアドレスが入っていますから、status[0]も*statusも同じデータを示します。ちなみに、C言語でstatus[0] と *(status + 0) と *(0 + status) と 0[status]が同じ意味になるのを知っていますか?

> あと、->は使えないんですか?

使う必要ありません。
そもそも、->がどういう意味かご存知でしょうか?
(*a).xと書く代わりに、a->xと書けるわけで、info関数のどこにその必要性がったのでしょうか?

あえて使うコードを考えるなら、statusの値をインクリメントしながら表示するコードにするなどがあるかもしれません。.x == 0を番兵 (http://ja.wikipedia.org/wiki/%E7%95%AA%E5%85%B5 )として置いておき、こんなふうに書くこともできます。
int main(void){
struct DATA student[] = {
{ 1, "a" },
{ 2, "b" },
{ 3, "c" },
{ 0, "sentinel"},
};
info(student);
return 0;
}

void info(struct DATA status[]){
for (;status->x != 0;status++) {
printf("%d %s\n", status->x, status->name);
}
}

あと、技術者同士の交流は相互扶助し、切磋琢磨しあうのが基本です。初心者だからだと気後れせず、答えられそうな質問を見つけたらどんどん回答してみてください。
    • good
    • 0
この回答へのお礼

対応ってそういうことだったんですね。
C++はCのちょっとした上位互換だと思っていたのでそこまで書き方が変わるとは思っていませんでした…


>配列変数は配列の先頭要素のアドレスが格納されていますので、それを引数に渡すということはアドレスを渡すということです。

つまり、例えば、a[3]という配列があったら
・a = &a[0] ということで、
 aを関数に渡すということは先頭配列のアドレスを渡しているということ。
・関数の仮引数を struct DATA *statusにすることで、関数はアドレスを受け取っている。
 さらに、struct DATA *status と struct DATA status[] は意味が同じだから、
 hanabutakoさんが書いてくださったコードにはポインタ宣言の*は必要がなかった。
という解釈で合ってますか?
何回も質問を重ねてしまって申し訳ないです。


>status[0] と *(status + 0) と *(0 + status) と 0[status]が同じ意味になるのを知っていますか?

0[status]なんて書き方もあるんですか!?知らなかったです。


->は使わない方が繰り返しとかは見やすいですね。
わざわざコードを提示していただいてありがとうございますm(_ _)m


答えられる質問を増やすためにもこれから精進したいと思います!
長くなってすいません。

お礼日時:2014/12/10 20:48

#3のお礼への返信です。



> つまり、例えば、a[3]という配列があったら
> ・a = &a[0] ということで、
>  aを関数に渡すということは先頭配列のアドレスを渡しているということ。

そうです。

> ・関数の仮引数を struct DATA *statusにすることで、関数はアドレスを受け取っている。
>  さらに、struct DATA *status と struct DATA status[] は意味が同じだから、
>  hanabutakoさんが書いてくださったコードにはポインタ宣言の*は必要がなかった。
という解釈で合ってますか?

そうです。
    • good
    • 0
この回答へのお礼

お礼遅くなってしまい申し訳ありません。

糖衣構文がよく分からなくてずっとつまづいていたので
今回、自分なりの理解ができてよかったです。

最後までこんな初歩的な質問に付き合ってくださってありがとうございました。

お礼日時:2014/12/12 20:53

struct DATA{


int x;
char name[32];
};

void info(DATA *status);

int main(void){
DATA student[3] = {
{ 1, "佐藤" },
{ 2, "高橋" },
{ 3, "田中" },
};
info(student);
return 0;
}

void info(DATA *status){
for (int i = 0; i < 3; i++){
printf("%d\n%s", status[i].x, status[i].name);
}
}

ただし、info() の中では渡されたものの長さがわからないため、
void info(DATA *status, int size){
for (int i = 0; i < size; i++){
printf("%d\n%s", status[i].x, status[i].name);
}
}
とした方がいいでしょう。
    • good
    • 0
この回答へのお礼

要素数の確認忘れてました…

おかげさまでたぶんエラーはなくなりました!
error LNK2019とかいうのが出てきてまだ試せていませんが…
ともあれ、ご回答ありがとうございました。

お礼日時:2014/12/08 22:20

C言語なのかC++なのか書かれていませんが、C言語なら、構造体を使うときはstruct 構造体名としなくてはいけません。


DATAではなく、struct DATAです。

また、関数の引数が変です。
main関数のstudentにはその構造体配列のアドレスが入っているので、渡すならinfo(student)です。受ける側もvoid info(struct DATA status[])と受けます。

#include <stdio.h>

struct DATA{
int x;
char name[32];
};

void info(struct DATA status[]);

int main(void){
struct DATA student[3] = {
{ 1, "佐藤" },
{ 2, "高橋" },
{ 3, "田中" },
};
info(student);
return 0;
}

void info(struct DATA status[]){
for (int i = 0; i < 3; i++){
printf("%d %s\n", status[i].x, status[i].name);
}
}
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
VC++ってCもC++も対応していませんでしたっけ?

C言語はstruct付けないといけないんですね。
自分の勉強不足さが身に染みてわかりました…

二つ疑問が…
この書き方ならポインタ宣言の*は書く必要はなく、
関数にアドレスが渡っているということですか?
あと、->は使えないんですか?
初心者でよくわかってないので説明していただけると嬉しいです。

お礼日時:2014/12/08 22:01

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!