【掲示板ご利用上の注意】

 ※題名は具体的に!
 ※学校の課題の丸投げ禁止!
 ※ソースの添付は「HTML変換ツール」で字下げ!
 ※返信の引用は最小限に!
 ※環境(OSとコンパイラ)や症状は具体的に詳しく!
 ※返信付き投稿の削除は禁止!
 ※マルチポスト(多重投稿)は慎んで!

 詳しくはこちら


本当はこんなに大きく書きたくはないのですが、なかなか守っていただけなくて…。
 守ってくださいね。お願いします。(by管理人)

C言語ソース⇒HTML形式ツール掲示板2こちら


管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.22108

構造体と関数
投稿者---neko(2005/07/25 15:52:10)


こちらのサイトの15-4-2の問題を自分なりに
解いてみましたが、エラーをどうなおしたらよいか
全く分かりません。
いろいろと考えたのですが、分からなかったので、
お手数ですが、よろしくお願いします。


#include<stdio.h>
#define KAMOKU 10

struct seiseki {
    int ten[KAMOKU + 1];
    int max;
    int min;
    double avg;
};

struct seiseki dataSyutoku (struct seiseki *data2);

int main(void)
{
    struct seiseki data[1] = {78, 86, 56, 77, 47, 63, 94, 37, 50, 74, -1, 0, 0, 0.0};
    struct seiseki data1;
    
    data1 = dataSyutoku(data);
    
    printf("max = %d min = %d avg = %f", data1.max, data1. min, data1.avg);
}
struct seiseki dataSyutoku (struct seiseki *data2)
{
    int i, total,  
    int  work = 0;
    while(data2->ten != -1) {
        total = (data2->ten) + total;
        data2++;
    }
    data2->avg = total / KAMOKU;
    
    while(data2->ten != -1) {
        for(i = 0; i < KAMOKU + 1; i++) {
            if(data2->ten >  (data2 + i)->ten) {
                work = data2->ten;
                (data2 + i)->ten = data2->ten;
                data2->ten = work;
                
            }
            data2->min = data2->ten;
            
            if(data2->ten <  (data2 + i)->ten) {
                work = data2->ten;
                (data2 + i)->ten = data2->ten;
                data2->ten = work;
            }
            data2->min = data2->ten;

        }

        data2++;
    }

    return data2;
}



警告 W8070 15-4-2.c 21: 関数は値を返すべき(関数 main )
エラー E2040 15-4-2.c 25: 宣言が正しく終了していない(関数 dataSyutoku )
警告 W8069 15-4-2.c 26: 移植性のないポインタ変換(関数 dataSyutoku )
警告 W8069 15-4-2.c 27: 移植性のないポインタ変換(関数 dataSyutoku )
警告 W8069 15-4-2.c 32: 移植性のないポインタ変換(関数 dataSyutoku )
エラー E2451 15-4-2.c 35: 未定義のシンボル work(関数 dataSyutoku )
エラー E2277 15-4-2.c 36: 左辺値が必要(関数 dataSyutoku )
警告 W8069 15-4-2.c 40: 移植性のないポインタ変換(関数 dataSyutoku )
エラー E2277 15-4-2.c 44: 左辺値が必要(関数 dataSyutoku )
警告 W8069 15-4-2.c 47: 移植性のないポインタ変換(関数 dataSyutoku )
エラー E2110 15-4-2.c 54: 互換でない型変換(関数 dataSyutoku )
*** 5 errors in Compile ***



この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:構造体と関数 22110 REE 2005/07/25 16:53:08
<子記事> Re:構造体と関数 22111 Tea 2005/07/25 17:13:19
<子記事> Re:構造体と関数 22113 まきじ 2005/07/25 18:54:54


No.22110

Re:構造体と関数
投稿者---REE(2005/07/25 16:53:08)


>こちらのサイトの15-4-2の問題を自分なりに
>解いてみましたが、エラーをどうなおしたらよいか
>全く分かりません。
>いろいろと考えたのですが、分からなかったので、
>お手数ですが、よろしくお願いします。

>int i, total,
コンマで終わっている


この投稿にコメントする

削除パスワード

No.22111

Re:構造体と関数
投稿者---Tea(2005/07/25 17:13:19)


>struct seiseki {
    int ten[KAMOKU + 1];
    int max;
    int min;
    double avg;
};

と ten は配列となっているのに対し、

>    while(data2->ten != -1)

のように要素番号が入っていないためだと思います。




この投稿にコメントする

削除パスワード

No.22113

Re:構造体と関数
投稿者---まきじ(2005/07/25 18:54:54)


>struct seiseki {
> int ten[KAMOKU + 1];
> int max;
> int min;
> double avg;
>};

問題は、ten は構造体に含まれていません。


この投稿にコメントする

削除パスワード

No.22120

Re:構造体と関数
投稿者---neko(2005/07/26 01:16:49)


REEさん、Teaさん、まきじさん
ありがとうございます。

REEさん
>コンマで終わっている

おっしゃる通りです。
修正しました。

Teaさん
>要素番号が入っていないためだと思います。

確かにそうです。
修正しました。

まきじさん
>問題は、ten は構造体に含まれていません。

確かにそうです。
一旦親記事のエラーを取りました。
下記に配列版も同様にかなり効率が悪いソースですが、
完成させました。

#include<stdio.h>
#define KAMOKU 10

struct seiseki {
    int ten[KAMOKU + 1];
    int max;
    int min;
    double avg;
};

struct seiseki dataSyutoku(struct seiseki *data2);

int main(void)
{
    struct seiseki data[1] = {78, 86, 56, 77, 47, 63, 94, 37, 50, 74, -1, 0, 0, 0.0};
    struct seiseki data1;
    
    data1 = dataSyutoku(data);
    
    printf("最高点 = %d\n 最低点 = %d\n 平均点 = %2.1f\n", data1.max, data1.min, data1.avg);
    return 0;
}
struct seiseki dataSyutoku(struct seiseki *data2)
{
    int i = 0, total = 0;  
    int  work_max, work_min;
    while(data2->ten[i] != -1) {
        total = (data2->ten[i]) + total;
        i++;
    }
    data2->avg = (double)total /(double)KAMOKU;
    
     work_max =  data2->ten[0];        
     work_min =  data2->ten[0];        
    for(i = 0; i < KAMOKU - 1; i++) {
        if(work_max < data2->ten[i + 1]) {
            work_max = data2->ten[i + 1];
        } else if(work_min > data2->ten[i + 1]){
            work_min = data2->ten[i + 1];
        }
        data2->max = work_max;
        data2->min = work_min;
    }
printf("data2->max%d data2->min%d\n ", data2->max, data2->min);
    return *data2;
}



配列版
これもかなり効率が悪くなってしまいました。

#include<stdio.h>
#define KAMOKU 10

struct seiseki {
    int max;
    int min;
    double avg;
};

struct seiseki dataSyutoku(int *ten1);

int main(void)
{
    struct seiseki data1;
    int ten[KAMOKU + 1] = {78, 86, 56, 77, 47, 63, 94, 37, 50, 74, -1};
    
    data1 = dataSyutoku(ten);
    
    printf("最高点 = %d\n 最低点 = %d\n 平均点 = %2.1f\n", data1.max, data1.min, data1.avg);
    return 0;
}
struct seiseki dataSyutoku(int *ten1)
{
    struct seiseki data2;
    int  work_max, work_min;
    int i = 0, total = 0;  
    while(*ten1 != -1) {
        total = *ten1 + total;
        ten1++;
        i++;
    }
    data2.avg = (double)total /(double)KAMOKU;
    for (i = 10; i > 0; i--) {
         ten1--;
         work_max =  *ten1;        
         work_min =  *ten1;
    }
    for(i = 0; i < KAMOKU ;i++) {
printf("*(ten1 + i) = %d\n", *(ten1 + i));    
        if(work_max < *(ten1 + i) ){
            work_max = *(ten1 + i);
        } else if(work_min > *(ten1 + i)){
            work_min = *(ten1 + i);
        }
        data2.max = work_max;
        data2.min = work_min;
    }
printf("data2.max%d data2.min%d\n ", data2.max, data2.min);
    return data2;
}






この投稿にコメントする

削除パスワード

No.22121

Re:構造体と関数
投稿者---Blue(2005/07/26 01:44:10)


> struct seiseki data[1] = {78, 86, 56, 77, 47, 63, 94, 37, 50, 74, -1, 0, 0, 0.0};
> data1 = dataSyutoku(data);
配列にする必要はないですね。アドレスを渡したいときは&を指定します。
struct seiseki data = {78, 86, 56, 77, 47, 63, 94, 37, 50, 74, -1, 0, 0, 0.0};
data1 = dataSyutoku( &data );

> struct seiseki dataSyutoku(struct seiseki *data2)
data2はポインタ渡しなので、dataSyutoku関数内で設定した値はmain関数に
戻ってきても有効です。
よって、
void dataSyutoku( struct seiseki* data2 );
でもいいでしょう。

ついでに、トータルを求める時に最大小値を求めると効率が良いです。

一例)
void dataSyutoku( struct seiseki* data2 )
{
    int i = 1, total = 0;
    int workten, workmax, workmin;
    
    total = workmax = workmin = data2->ten[ 0 ];
    
    while ( ( workten = data2->ten[ i++ ] ) != -1 )
    {
        total += workten;
        if ( workmax < workten )
        {
            workmax = workten;
        }
        else if ( workmin > workten )
        {
            workmin = workten;
        }
    }
    
    data2->avg = ( double )total / KAMOKU;
    data2->max = workmax;
    data2->min = workmin;
}

# 配列数が固定ならばいちいちターミネータ(-1)を用意しなくてもいい気がしますが。



この投稿にコメントする

削除パスワード

No.22125

Re:構造体と関数
投稿者---neko(2005/07/26 10:52:27)


ありがとうございます。
変更してコンパイルしてみました。

>data1 = dataSyutoku( &data );

ここの部分(18行目)でエラーと警告が出ました。
なぜでしょうか?
22行目はmain関数の最後の括弧です。

警告 W8075 15-4-2_struct関数struct引数版_keijiban.c 18: 問題のあるポインタの変換(関数 main )
エラー E2109 15-4-2_struct関数struct引数版_keijiban.c 18: 許されない型(関数 main )
警告 W8004 15-4-2_struct関数struct引数版_keijiban.c 22: 'data' に代入した値は使われていない(関数 main )

>void dataSyutoku( struct seiseki* data2 );

void dataSyutoku( struct seiseki *data2 );
の違いは何でしょうか?*印がseisekiの直後に付くか
data2の直前に付いているかの違いなのですが、、。

>ついでに、トータルを求める時に最大小値を求めると効率が良いです。

なるほどです。

> int i = 1, >total = 0;
> int workten, workmax, workmin;

> total = workmax = workmin = data2->ten[ 0 ];

> while ( ( workten = data2->ten[ i++ ] ) != -1 )
> {
> total += workten;
> if ( workmax < workten )


まずiに1を入れて配列の中身0と比較する方法もなるほどだと思いました。
こういう方法もあったのですね。


># 配列数が固定ならばいちいちターミネータ(-1)を用意しなくてもいい気がしますが。

可変ではないですのでそうですね。





この投稿にコメントする

削除パスワード

No.22130

Re:構造体と関数
投稿者---Blue(2005/07/26 15:14:13)


> void dataSyutoku( struct seiseki *data2 );
> の違いは何でしょうか?*印がseisekiの直後に付くか
> data2の直前に付いているかの違いなのですが、、。
違いは値を返すかどうかです。dataSyutoku内で直接data2の変更させるので
戻り値はいらないということです。

ちなみに ポインタの * の位置はあまり関係ないです。
int* p;
でも
int *p;
でも
int * p;
でも同じように
[int][*][p]のようにトークン分割されます。書き方は好みなのです。

> ここの部分(18行目)でエラーと警告が出ました。
> なぜでしょうか?
struct seiseki data[ 1 ];
を変更しましたか?
配列に&をつけているとかそういうことはないですよね?

変更後のプロトタイプ宣言とmain文)
void dataSyutoku(struct seiseki *data2);

int main(void)
{
    struct seiseki data = {78, 86, 56, 77, 47, 63, 94, 37, 50, 74, -1, 0, 0, 0.0};
    
    dataSyutoku(&data);
    
    printf("最高点 = %d\n 最低点 = %d\n 平均点 = %2.1f\n", data.max, data.min, data.avg);
    return 0;
}



この投稿にコメントする

削除パスワード

No.22132

Re:構造体と関数
投稿者---neko(2005/07/26 15:35:42)


ありがとうございます。

>dataSyutoku内で直接data2の変更させるので戻り値はいらないということです。

分かりました。

>[int][*][p]のようにトークン分割されます。書き方は好みなのです。

はい。これも良く分かりました。

>struct seiseki data[ 1 ];
>を変更しましたか?

変更してませんでした。
しかしなぜ[1]としたまま
dataSyutoku(&data);
とするとエラーになるのでしょうか?
data[1]の先頭のアドレスとdataにした時の
先頭アドレスは同じではないのでしょうか?


>変更後のプロトタイプ宣言とmain文)

ありがとうございました。
お蔭様で出来ました。



この投稿にコメントする

削除パスワード

No.22134

Re:構造体と関数
投稿者---Blue(2005/07/26 15:51:28)


>data[1]の先頭のアドレスとdataにした時の
>先頭アドレスは同じではないのでしょうか?
strcut seiseki data[ 1 ];
dataSyutoku(&data);
ですと、関数呼び出し時には struct seiseki* 型で渡すようにしているのを
struct seiseki** 型で渡してしまいます。
よって、
>警告 W8075 15-4-2_struct関数struct引数版_keijiban.c 18: 問題のあるポインタの変換(関数 main )
>エラー E2109 15-4-2_struct関数struct引数版_keijiban.c 18: 許されない型(関数 main )
というエラーが出るわけです。


strcut seiseki data[ 1 ];
で宣言されている場合

data       ← 配列の先頭を示すアドレス
&data[ 0 ] ← dataと同様
&data      ← 配列の先頭を示すアドレスが格納されているアドレス
              いわゆる struct seiseki**型



この投稿にコメントする

削除パスワード

No.22151

Re:構造体と関数
投稿者---neko(2005/07/26 22:30:02)


ありがとうございます。

>strcut seiseki data[ 1 ];
>で宣言されている場合

>data ← 配列の先頭を示すアドレス
>&data[ 0 ] ← dataと同様

ここまでは分かります。


>&data ← 配列の先頭を示すアドレスが格納されているアドレス
> いわゆる struct seiseki**型</pre>

いろいろと本を引っ張り出して調べたり、ネット上で調べてもここの部分
は分かりませんでした。
理屈が分かりません。丸暗記しかないのでしょうか?
お手数ですが、よろしくお願いします。



この投稿にコメントする

削除パスワード

No.22153

Re:構造体と関数
投稿者---まきじ(2005/07/26 22:47:35)


>>&data ← 配列の先頭を示すアドレスが格納されているアドレス
>> いわゆる struct seiseki**型
>ここの部分は分かりませんでした。

>>data ← 配列の先頭を示すアドレス
>>&data[ 0 ] ← dataと同様
>ここまでは分かります。

でしたら、data は struct seiseki* 型なのは解りますよね?

int x = 10;
int *p = &x;

と同じ考えですよね?

p のアドレスを変数に格納するには int** 型の変数が必要ですので

int **pp = &p;

で、x のアドレスを持った、ポインタ変数 p のアドレスを、
ダブルポインタ変数 pp に格納することができます。

data も同じ様に、data のアドレスを格納するには struct seiseki** 型
の変数が必要ですので、

struct seiseki** pdata = &data;

で、data のアドレスを、ダブルポインタ変数 pdata に格納することができます。

よって、&data は struct seiseki** 型になります。


この投稿にコメントする

削除パスワード

No.22162

Re:構造体と関数
投稿者---neko(2005/07/26 23:42:57)


ありがとうございます。

>でしたら、data は struct seiseki* 型なのは解りますよね?
>
>int x = 10;
>int *p = &x;
>
>と同じ考えですよね?

はい。分かります。

>p のアドレスを変数に格納するには int** 型の変数が必要ですので
>
>int **pp = &p;
>
>で、x のアドレスを持った、ポインタ変数 p のアドレスを、
>ダブルポインタ変数 pp に格納することができます。
>
>data も同じ様に、data のアドレスを格納するには struct seiseki** 型
>の変数が必要ですので、
>
>struct seiseki** pdata = &data;
>
>で、data のアドレスを、ダブルポインタ変数 pdata に格納することができます。
>
>よって、&data は struct seiseki** 型になります。

はい。ここも分かります。
下記1行だけを見たら確かに1行分の意味は
それぞれ分かります。
int x = 10;
int *p = &x;
int **pp = &p;
ですが、&p;→これだけを見て
int x = 10;
int *p = &x;
の部分があるということが
想像出来ないでいます。





この投稿にコメントする

削除パスワード

No.22166

Re:構造体と関数
投稿者---まきじ(2005/07/27 00:05:51)


>int **pp = &p;
>ですが、&p;→これだけを見て

そこだけに着目する必要はないと思います。
前後や宣言部などを見ないと解らないことはあります。

data はstruct seiseki 型の配列だという事が、宣言部を見て解ってますので
&data は struct seiseki** 型 ということが解ります。


この投稿にコメントする

削除パスワード

No.22169

Re:構造体と関数
投稿者---かずま(2005/07/27 02:26:11)


> data も同じ様に、data のアドレスを格納するには struct seiseki** 型
> の変数が必要ですので、
>
> struct seiseki** pdata = &data;
>
> で、data のアドレスを、ダブルポインタ変数 pdata に格納することができます。
>
> よって、&data は struct seiseki** 型になります。

違います。次のプログラムをコンパイルしてみてください。
struct seiseki { int v; };

int main(void)
{
    struct seiseki data[1];
    struct seiseki **pdata = &data;

    return 0;
}



この投稿にコメントする

削除パスワード

No.22171

Re:構造体と関数
投稿者---まきじ(2005/07/27 08:37:51)


>違います。次のプログラムをコンパイルしてみてください。

本当ですね。

warning C4047: 'initializing' : 'seiseki ** ' differs in levels of indirection from 'seiseki (*)[1]'

というエラーがでました

&data は struct seiseki (*)[1] 型 なんですね。


この投稿にコメントする

削除パスワード

No.22168

Re:構造体と関数
投稿者---かずま(2005/07/27 02:14:07)


> strcut seiseki data[ 1 ];
> dataSyutoku(&data);
> ですと、関数呼び出し時には struct seiseki* 型で渡すようにしているのを
> struct seiseki** 型で渡してしまいます。

違います。&data は、struct seiseki (*)[1] 型です。

関数 dataSyutoku は、引数に struct seiseki * 型を要求するので警告が出ます。


この投稿にコメントする

削除パスワード

No.22170

Re:構造体と関数
投稿者---Blue(2005/07/27 02:35:16)


> 違います。&data は、struct seiseki (*)[1] 型です。
struct seiseki** 型の変数に代入しようとしたところ、

error C2440: '=' : 'struct seiseki (*)[1]' から 'struct seiseki ** ' に変換することはできません。

とエラーが出ました。(VC6)

> &data      ← 配列の先頭を示すアドレスが格納されているアドレス
>               いわゆる struct seiseki**型
はまったくの間違いでした。

配列のアドレス演算子における理解が不足していたようです。
ご指摘ありがとうございました。



この投稿にコメントする

削除パスワード

No.22176

Re:構造体と関数
投稿者---neko(2005/07/27 10:32:35)


まきじさん、かずまさん、Blueさんありがとうございました。

頭ごちゃごちゃで消化不良ですが、
つまり
>data
>&data[ 0 ]
>&data
も配列の先頭を示すアドレスということでしょうか?



この投稿にコメントする

削除パスワード

No.22181

Re:構造体と関数
投稿者---とおり(2005/07/27 10:58:34)


>頭ごちゃごちゃで消化不良ですが、
>つまり
>>data
>>&data[ 0 ]
>>&data
>も配列の先頭を示すアドレスということでしょうか?

例えば、
int data[10];
と宣言した時、
data でも &data[0] でも同じことになります。
しかし、data と &data は違います。
(&data は data のアドレスが格納される)

ので、
>data は配列の先頭を示すアドレス
>&data[ 0 ] 配列の先頭を示すアドレス
>&data 配列の先頭を示すアドレスのアドレス


この投稿にコメントする

削除パスワード

No.22185

Re:構造体と関数
投稿者---neko(2005/07/27 11:20:08)


ありがとうございます。

>>>&data 配列の先頭を示すアドレスのアドレス

はい。分かりました。



この投稿にコメントする

削除パスワード

No.22186

Re:構造体と関数
投稿者---YuO(2005/07/27 11:22:08)


>>data は配列の先頭を示すアドレス
>>&data[ 0 ] 配列の先頭を示すアドレス
>>&data 配列の先頭を示すアドレスのアドレス

違います。

data
(dataという名前の付いた)配列オブジェクトそのもの。配列型のオブジェクトは,いくつかの例外を除いて,その配列の最初の要素を指すポインタに変換されます。
&data
(dataという名前の付いた)配列オブジェクトへのポインタ。
&data[0]
(dataという名前の付いた)配列オブジェクトの先頭要素へのポインタ。


dataはあくまで配列であり,ポインタではないです。



この投稿にコメントする

削除パスワード

No.22187

Re:構造体と関数
投稿者---とおり(2005/07/27 11:24:26)


>>>data は配列の先頭を示すアドレス
>>>&data[ 0 ] 配列の先頭を示すアドレス
>>>&data 配列の先頭を示すアドレスのアドレス
>
>違います。
>
>
data
(dataという名前の付いた)配列オブジェクトそのもの。配列型のオブジェクトは,いくつかの例外を除いて,その配列の最初の要素を指すポインタに変換されます。
&data
(dataという名前の付いた)配列オブジェクトへのポインタ。
&data[0]
(dataという名前の付いた)配列オブジェクトの先頭要素へのポインタ。

>
>dataはあくまで配列であり,ポインタではないです。


あらま。。。
こりゃ失礼。



この投稿にコメントする

削除パスワード

No.22189

Re:構造体と関数
投稿者---とおり(2005/07/27 11:39:29)


>>>data は配列の先頭を示すアドレス
>>>&data[ 0 ] 配列の先頭を示すアドレス
>>>&data 配列の先頭を示すアドレスのアドレス
>
>違います。
>
data
(dataという名前の付いた)配列オブジェクトそのもの。配列型のオブジェクトは,いくつかの例外を除いて,その配列の最初の要素を指すポインタに変換されます。
&data
(dataという名前の付いた)配列オブジェクトへのポインタ。
&data[0]
(dataという名前の付いた)配列オブジェクトの先頭要素へのポインタ。

>
>dataはあくまで配列であり,ポインタではないです。

私にこれほどの理解はありませんが、

>>data は配列の先頭を示すアドレスを返してくれる
>>&data[ 0 ] 配列の先頭を示すアドレスを返してくれる
>>&data 配列の先頭を示すアドレスのアドレスを返してくれる

の理解はあっていますか? >YuOさん

#なんかもうなにがなんだか。。。


この投稿にコメントする

削除パスワード

No.22190

Re:構造体と関数
投稿者---YuO(2005/07/27 12:07:10)


>>>data は配列の先頭を示すアドレスを返してくれる
>>>&data[ 0 ] 配列の先頭を示すアドレスを返してくれる
>>>&data 配列の先頭を示すアドレスのアドレスを返してくれる
>の理解はあっていますか? >YuOさん

最後が間違っています。
とりあえず,アドレスをポインタと読み替えるとして,
&dataは配列へのポインタであって,
配列の先頭要素のポインタへのポインタ,というわけのわからないものではありません。
# ポインタとは値であり,オブジェクトではない。


この投稿にコメントする

削除パスワード

No.22192

Re:構造体と関数
投稿者---とおり(2005/07/27 13:12:19)


>>>>data は配列の先頭を示すアドレスを返してくれる
>>>>&data[ 0 ] 配列の先頭を示すアドレスを返してくれる
>>>>&data 配列の先頭を示すアドレスのアドレスを返してくれる
>>の理解はあっていますか? >YuOさん
>
>最後が間違っています。
>とりあえず,アドレスをポインタと読み替えるとして,
>&dataは配列へのポインタであって,
>配列の先頭要素のポインタへのポインタ,というわけのわからないものではありません。
># ポインタとは値であり,オブジェクトではない。

ん?んん???
なんか混乱してきたぞ??

ん〜。もうちょっと考えてみてわかんなかったら別スレおこすかな

&data ってどんな時に使うんだろ?


この投稿にコメントする

削除パスワード

No.22213

Re:構造体と関数
投稿者---Hermit(2005/07/27 19:31:29)


二つの捕らえ方があるようで、
K&Rの様に、配列に対しては無視と、
配列へのポインタがあったと記憶しています。

前者が、bc,vc
後者が gcc,lsic
など
ANSIはどうなってるんだろ?

あ、&& にすると、bc,vc で動作が変わった気がします。
c++ではどうだったろう、
ボーランドでは、バージョンによって動作が違ってはずです。


この投稿にコメントする

削除パスワード

No.22215

Re:構造体と関数
投稿者---YuO(2005/07/27 20:03:20)


>K&Rの様に、配列に対しては無視と、
>前者が、bc,vc

配列に対して単項&演算子を適用した場合の話ですよね。

BCCやVC++は,無視してはいませんよ。
実装上のポインタの値が変化しないので,
値を修正するコードは含まれないでしょうが,
実際には配列へのポインタをちゃんと生成します。

型をちゃんと考えましょう。


>ANSIはどうなってるんだろ?

ISO/IEC 9899:1999 6.3.2.1 Lvalues, arrays, and function designators / Paragraph 2

Except when it is the operand of the sizeof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the . operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object.



でもって,6.5.3.2 Address and indirection operatorsに,配列を特別視するような記述はありません。

故に,配列オブジェクトに単項&演算子を適用した場合は,
常に配列へのポインタを生成します。



この投稿にコメントする

削除パスワード

No.22221

Re:構造体と関数
投稿者---Hermit(2005/07/27 22:35:58)


>故に,配列オブジェクトに単項&演算子を適用した場合は,
>常に配列へのポインタを生成します。

最近のはそうなんですか。
まだ、bc++5.51(ふりーのやつ)しか使ってなかったので(^^;

#include <stdio.h>

int main() {
char foo[5];
printf("sizeof foo %d\nsizeof &foo %d\n",sizeof(foo),sizeof(&foo));
printf("foo pointer %p\n&foo pointer %p\n&foo + 1 pointer %p\n",foo,&foo,(&foo)+1);
return 0;
}
bc++5.51 では、foo,&fooとも同じだと思いますが。

言ってる意味が YuO さんの言ってる意味が違ったらごめんなさい。



この投稿にコメントする

削除パスワード

No.22222

Re:構造体と関数
投稿者---Hermit(2005/07/27 22:39:21)



>言ってる意味が YuO さんの言ってる意味が違ったらごめんなさい。

私の言ってる意味が YuO さんの言ってる意味と違ったらごめんなさい。



この投稿にコメントする

削除パスワード

No.22225

Re:構造体と関数
投稿者---Hermit(2005/07/27 23:24:09)


あ、BC++5.51 は無視してませんね(^^;
失礼しました。
foo 全体へのポインタになってるんですね。

昔の gcc lsic86 は、sizeof(&foo) が 4 だったので、
どちらがほんとだろうと思ってたので、混乱してたようです。

VC++ などは、どうなってるんでしょう?
動作が違ってる記憶があるんですが。
&&foo が、どちらかがエラーになった記憶があったので
多分 VC++ は通る気が。
&foo の動作は同じなのかな?


この投稿にコメントする

削除パスワード

No.22226

Re:構造体と関数
投稿者---YuO(2005/07/28 01:49:26)


とにかく勉強して下さい。
配列型のオブジェクトに対して単項&演算子を適用した結果について,
標準は一つの解釈しか与えていません。


> foo 全体へのポインタになってるんですね。

そういうことです。
特別なことでもなんでもないのですが……。


>VC++ などは、どうなってるんでしょう?
>動作が違ってる記憶があるんですが。
>&&foo が、どちらかがエラーになった記憶があったので

&&fooというのは,
二項演算子&&と識別子fooがあると,コンパイラによって解釈されます。
この場合,fooという識別子が配列型のオブジェクトを指しているのであれば,
この左辺値は配列の先頭要素へのポインタという値に変換されます。


>多分 VC++ は通る気が。
>&foo の動作は同じなのかな?

「何」と「何」が同じなのですか?

配列型のオブジェクトに対する単項&演算子の動作に関して,
Microsoft 32-bit C/C++ Compilerの,少なくともVersion 11は,
標準通りの動作を行います。

これは,Borland C++ Compiler 5.5.1においても確認しています。



この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧