関数に構造体を渡したいのですが、エラーが出て上手くいきません。
下のプログラムのように組んでいるのですが、どこが問題なのかご教授願いたいです。
もし、下記のプログラムのようなことができないのでしたら、代替案を提示してもらえると助かります。
環境は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);
}
}
No.3ベストアンサー
- 回答日時:
お礼への返信です。
> 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);
}
}
あと、技術者同士の交流は相互扶助し、切磋琢磨しあうのが基本です。初心者だからだと気後れせず、答えられそうな質問を見つけたらどんどん回答してみてください。
対応ってそういうことだったんですね。
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
答えられる質問を増やすためにもこれから精進したいと思います!
長くなってすいません。
No.4
- 回答日時:
#3のお礼への返信です。
> つまり、例えば、a[3]という配列があったら
> ・a = &a[0] ということで、
> aを関数に渡すということは先頭配列のアドレスを渡しているということ。
そうです。
> ・関数の仮引数を struct DATA *statusにすることで、関数はアドレスを受け取っている。
> さらに、struct DATA *status と struct DATA status[] は意味が同じだから、
> hanabutakoさんが書いてくださったコードにはポインタ宣言の*は必要がなかった。
という解釈で合ってますか?
そうです。
お礼遅くなってしまい申し訳ありません。
糖衣構文がよく分からなくてずっとつまづいていたので
今回、自分なりの理解ができてよかったです。
最後までこんな初歩的な質問に付き合ってくださってありがとうございました。
No.2
- 回答日時:
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);
}
}
とした方がいいでしょう。
要素数の確認忘れてました…
おかげさまでたぶんエラーはなくなりました!
error LNK2019とかいうのが出てきてまだ試せていませんが…
ともあれ、ご回答ありがとうございました。
No.1
- 回答日時:
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);
}
}
ご回答ありがとうございます。
VC++ってCもC++も対応していませんでしたっけ?
C言語はstruct付けないといけないんですね。
自分の勉強不足さが身に染みてわかりました…
二つ疑問が…
この書き方ならポインタ宣言の*は書く必要はなく、
関数にアドレスが渡っているということですか?
あと、->は使えないんですか?
初心者でよくわかってないので説明していただけると嬉しいです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- C言語・C++・C# C言語 プログラミング 4 2022/05/22 11:53
- C言語・C++・C# 10個の実数に対する降順ソート結果を出力するプログラムを作りたいのですが、以下のプログラムをどう直せ 1 2022/07/09 22:16
- C言語・C++・C# 未解決の外部シンボル _printfが関数_mainで参照されました 1 2022/09/18 15:28
- C言語・C++・C# カードシャッフルのブログラムを使ってc言語でブラックジャックをしたい 2 2022/04/12 15:13
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# C言語初心者 構造体 課題について 1 2023/03/10 19:30
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
- C言語・C++・C# Cのdoubleの浮動小数点表示について 3 2023/04/17 13:14
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
関数から配列を返すには?
-
構造体のextern方法
-
配列の要素数に変数を入れたい...
-
無作為に選択
-
C言語についてです 5人のテスト...
-
n人の教科ごとの最高点、最低点...
-
C言語 ファイルの指定された行...
-
C言語から質問です。
-
C言語において、 配列要素をひ...
-
C#で構造体の配列を持った構造...
-
[C++]const int と配列
-
c言語 構造体
-
fclose()でセグメンテーション違反
-
c言語の自分で数字を入力してサ...
-
define で 配列
-
c言語
-
コンボボックスでデフォルト値...
-
C言語 数値の連続入力について
-
.NET C++で、構造体の配列をnew...
-
メンバ変数の取得
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
おすすめ情報