- C言語 構造体ポインタを使用した関数の扱いについて教えてください。

ゲスト (Tanaka)

問題文:氏名と点数を入力する処理をn
Main関数でそれを呼び出し&表示するプログラムを作成せよ。
環境
OS:Vista
コンパイラー:Bcc32
使用言語:C言語
#include
struct
char
int
};
struct
struct
void
int
int
int
input_score(element,n);
for(i=0;i<n;i++){
printf("name:%s
}
return
}
void
int
for(i=0;i<n;i++){
printf("name:");
scanf("%s",(a[i]->name));
printf("score:");
scanf("%d",&(a[i]->score));
}
}
なにがまずいのか指摘していただけると助かります。
よろしくお願いします。
コメント

- 2:ゲスト (Tanaka)
- 2008/01/14 03:31
ありがとうございます。
なるほど。
input_score関数内で、構造体_TEST
何故、a[i].name
a[i]->name のようなアドレス演算子を使うべきところではないのでしょうか?

- 3:ゲスト (暇人)
- 2008/01/14 14:48
例えば、
//
//この時、p[i]
質問文での主張はアドレスであるということであり、
コメントの主張は配列の1つの要素であるということです。

- 4:ゲスト (Tanaka)
- 2008/01/15 02:32
回答ありがとうございます。
私は以下のように理解しました。
1.p
2.a[3]:配列aの3という要素そのものを指す。
p[3]:配列aの3のアドレスを指し示すもの。(つまり→ *p[3]=a[3])
そして、構造体において同様に理解すると、
(投稿されたソース)a
a[i]->nameと使用するのが正しいと考えられるのですが、この思考はどこがおかしいのでしょうか?

- 5:ゲスト (暇人)
- 2008/01/15 07:44
>2.a[3]:配列aの3という要素そのものを指す。
>p[3]:配列aの3のアドレスを指し示すもの。(つまり→ *p[3]=a[3])
それ(a[3]とp[3])を区別するのが(というか動作の理解が)間違っていますね。
配列演算子は、
アドレス[その型の要素の位置]でその型の要素を取り出すものです。
その意味で、
a[3]とp[3]は同じモノです。
言い換えれば
p[3]は、*(p+3)と等価な演算をします。
a[3]=p[3]=*(p+3)=*(a+3)
です

- 6:ゲスト (Tanaka)
- 2008/01/15 12:26
回答ありがとうございます。
私は以下のように理解しました。
1.配列である ⇒ アドレスであるということ。
p
2.元のソースに戻って、a[i]->name
何故ならば、a[i]->name
例えば、printf("%d",*p[i]);
ありがとうございました。疑問が解決致しました。
しかし…配列そのものがポインタだと理解するならば、配列にポインタを定義する(p

- 7:ゲスト
- 2008/01/15 15:09
>配列そのものがポインタだと理解するならば
配列
a
[]
「配列そのもの」がポインタというのは語弊があります。
>配列を使用する場合はポインタは不要なのでしょうか?
質問の意図するところがわかりませんが、
例えば、
input_score(&element[3],3);
で呼び出すこともできますし、
for
つまり
for(i=0;i<n;i++,a++){
なんてすれば、
scanf("%s",a->name);
とできて、
この場合、配列アクセスのためのアドレス演算がちょっと省略(構造体メンバ毎に同じ計算をしなくてもよい)できます。

- 8:ゲスト (Tanaka)
- 2008/01/15 16:35
回答ありがとうございます。
勉強になります。
私は以下のように理解しました。
配列はあくまで、配列の先頭要素のアドレスを指すもので配列そのものではないということ。
int
a[1]のアドレス…0000000A
a[2]のアドレス…00000014
のようになってるとすると。
a[1]は0000000Aという番地そのものを指すポインタであるといえる。
a[2]も00000014という番地のポインタであるといえる。
<話題その1>
質問の意図が伝わらなくて申し訳ありません。
配列がポインタであるならば、
int
<話題その2>
ちなみに、scanf("%s",a->name);に変更して実行したところ、i=n(つまりi=6)の結果しか代入されないようなのですが。
<話題その3>
また、教えていただいたように、a[1]=p[1]=*(a+1)=*(p+1)だと理解すると、
問題文に沿ったプログラム内において、
scanf("%s",(
という記述は間違ってはいないと考えます。
考え方に間違いが生じているのでしょうか?

- 9:ゲスト (暇人)
- 2008/01/15 17:56
>配列はあくまで、配列の先頭要素のアドレスを指すもので配列そのものではないということ。
例えば、
int
int
の時
sizeof(data)
sizeof(p)
は、どのような結果になると思いますか?
>a[1]は0000000Aという番地そのものを指すポインタであるといえる。
その番地から要素を取り出すという意味でポインタと言ってもいいような気がするけど、
それをいうなら
int
だって、
変数iは、i
>p=a;といったような使用方法にメリットはないのではないか
ポインタを使って配列にアクセスすることにメリットはあるよ。
すでに示したつもり。
>scanf("%s",a->name);に変更して実行したところ、i=n(つまりi=6)の結果しか代入されないようなのですが。
前後(他)の部分で間違いがあると思う。
>scanf("%s",(
>という記述は間違ってはいないと考えます。
scanf("%s",(
と
scanf("%s",(
が同じという意味で
"yes"

- 10:ゲスト
- 2008/01/17 19:09
以下の説明はけっこう乱暴です。
しかし的は外してないと思います。
int
int*
と宣言されているとして説明します。
1.
・論理的な問題、C言語の決まりごとの問題
・文法上の問題、書き方の問題
この2つを分けて考えましょう。
2.
論理的な問題です。
ポインタと配列は全く違います。
というか同じレベルで語るものではないです。
ポインタは変数です。
変数には値型変数とポインタ型変数があるのです。
(値型変数というのは
で、配列というのは複数の変数が連続したものですね。
3.
論理的な問題です。
アドレスは「何の」アドレスなのかが重要です。
ポインタに関しては2種類のアドレスがあります。
・ポインタ自体のアドレス
・ポインタが指すアドレス
どうもこの2つを混同しているように思えます。
代入で変更できるのは「ポインタが指すアドレス」だけです。
4.
論理的な問題です。
.演算子や->演算子は変数に対してしか使用できません。
.演算子は値型変数に対して使い、->演算子はポインタ型変数に対して使います。
a->name
論理的にはやや破綻しています。
それは
5.
文法的な問題です。
各式が表す「値」の型を考えてみましょう。
&a[0]...ポインタ型変数(int*型)
a[0]...値型変数(int型)
p...ポインタ型変数(int*型)
*p...値型変数(int型)
&p...ポインタ型変数(int**型、ポインタのポインタ)
6.
文法的な話です。
C言語では型変換つまりキャストがあちこちで行われます。
文法的に型のおかしい変数があると勝手にキャストが行われます。
例えばlong型変数とint型変数の値を比較する際には、int型変数はlong型にキャストされます。別な型のままだと比較できないからです。
これは暗黙的に行われますが、プログラマは知っておかなければなりません。
結論から言ってしまえば[]演算子を使うその瞬間だけは、aはポインタ型変数にキャストされており、そのキャストの際にaの先頭アドレスが代入されているのです。C言語ではそういう「配列→ポインタ型変数」のキャストが最初から規定されているのです。
これはC言語を作った人たちが「[]演算子使う時や先頭アドレス取ってくる時に、ポインタと配列を同じように扱えたら便利だな~」と思って勝手に(?)決めた約束事です。
要するにポインタと配列は別物なのですが、特定のケースで同じように使えるようにしてあるだけなのです。
前へ 1 次へ![]()
コメントする
[block]から[/block]までの範囲はブロック表示されます。
部分的に目立たせたい時や、引用などにお使いください。
[code]から[/code]までの範囲は等幅表示されます。
ソースコードや設定ファイルの記述などにお使いください。







#include <stdio.h>
DATA_SIZE 6
_TEST{
char name[100];
int score;
_TEST element[DATA_SIZE];
struct _TEST *a[DATA_SIZE]; */
input_score( struct _TEST *a, int n );
main (void){
int n = DATA_SIZE;
int i = 0;
input_score(element,n);
for(i=0;i<n;i++){
printf("name:%s , score:%d \n", element[i].name, element[i].score);
}
return 0;
input_score( struct _TEST *a, int n ){
int i;
for(i=0;i<n;i++){
printf("name:");
scanf("%s", a[i].name);
printf("score:");
scanf("%d", &(a[i].score));
}
#define
struct
};
struct
/*
void
int
}
void
}