構造体

[戻る]
どたんば 2003/02/05(水) 00:04:32
#include <stdio.h>

    struct CPU{
        char   name;
        int    syuuhasuu;
        double chokkei;
        double takasa;
    };
    struct CPU first;

int main(void)
{
    printf("それぞれに値を入力してください。\n");
    printf("名前-->");    scanf("%s", &first.name);
    printf("周波数-->");  scanf("%d", &first.syuuhasuu);
    printf("直径-->");    scanf("%lf", &chokkei);
    printf("高さ-->");    scanf("%lf", &takasa);

    return (0);
}     

なんですか直径までうまくいくんですがそのあとEnterを押すと
デバッグエラーと出てしまいまいます。
なぜでしょうか?

c 2003/02/05(水) 00:07:35
printf("直径-->");    scanf("%lf", &first.chokkei);
printf("高さ-->");    scanf("%lf", &first.takasa);

NTAKA 2003/02/05(水) 00:10:01
構造体についてもう少し理解を深めた方が・・・
ちなみに、それってコンパイルできたんでしょうか?

どたんば 2003/02/05(水) 00:13:19
すいません。
保存前のを載せてしまいました。
printf("直径-->");    scanf("%lf", &first.chokkei);
printf("高さ-->");    scanf("%lf", &first.takasa);
で実行してもだめなんですよ。

暇人貴子 2003/02/05(水) 00:16:03
>    printf("名前-->");    scanf("%s", &first.name);
も変ですね。

どたんば 2003/02/05(水) 00:27:05
すいません。
具体的にどこがおかしいのでしょうか?
おねがいします。

επιστημη 2003/02/05(水) 00:48:46
first.nameはたった1文字分の領域しかありません。

wood 2003/02/05(水) 05:04:44
>first.nameはたった1文字分の領域しかありません。

struct CPU{
   char   name[2];
     .
     .
     .
にしても
>printf("直径-->");    scanf("%lf", &first.chokkei);
でランタイム エラー出るみたいですね
昔はコンソール上に「R6002 」なんて出たんですけど
今はWindowsがただ「ランタイム エラー」メッセージ出すだけで
エラーナンバーわかりゃしない

でも、それ+
>first.chokkei
を初期化すると
>first.takasa
を初期化しなくても
>printf("高さ-->");    scanf("%lf", &first.takasa);
も通るね

どうも私も、この辺の理解度が低くて誰かフォローお願いします

アイススケーター 2003/02/05(水) 08:06:47
#include <stdio.h>

    struct CPU{
        char   name[8];
        int    syuuhasuu;
        double chokkei;
        double takasa;
    };
    struct CPU first;

int main(void)
{
    printf("それぞれに値を入力してください。\n");
    printf("名前-->");    scanf("%s", first.name);    <-ここ直しました
    printf("周波数-->");  scanf("%d", &first.syuuhasuu);
    printf("直径-->");    scanf("%lf", &first.chokkei);
    printf("高さ-->");    scanf("%lf", &first.takasa);

    return (0);
}     

でエラーが出なくなりましたが???

でも、最初ソースをコピーしてRUNしたら「ランタイム エラー」が出てましたね〜?

Green 2003/02/05(水) 09:15:01
アイススケーターさんが直してくれていますが・・・

>    struct CPU{
>        char   name;
>        int    syuuhasuu;
>        double chokkei;
>        double takasa;
>    };

この構造体だと意図通りに動いてくれないと思います。
構造体は通常各要素が4バイト境界で切れていなければなりません。
ちょっと説明が難しいのですが次のようなプログラムを動かして頂ければ
分かると思います。


#include <stdio.h>

    struct CPU{
        char   name;
        int    syuuhasuu;
        double chokkei;
        double takasa;
    };
    struct CPU first;

int main(void)
{
    printf("0x%X ", &first.name);
    printf("0x%X ", &first.syuuhasuu;
    printf("0x%X ", &first.chokkei;);
    printf("0x%X\n", &first.takasa;);

    return (0);
}

このプログラムは構造体の各要素のアドレスを表示するものですが実行すると

0x0 0x4 0x8 0x10
※便宜上オフセットで書いています。

のようになります。通常nameが1バイトですから二番目のアドレスは0x1に成らなければ
いけないのですがsyuuhasuuが4バイト境界をまたがっているためこのように4バイト境界
で切れるようにnameのあとに3バイト詰め物されます。このせいで最後のtakasaにアクセ
スしようとすると構造体の領域外にアクセスしてしまいメモリ破壊を起こすこともあります。

Green 2003/02/05(水) 09:27:06
良く考えるとこの構造体もちょっと引っかかりますね。

>    struct CPU{
>        char   name[8];
>        int    syuuhasuu;
>        double chokkei;
>        double takasa;
>    };

この場合、chokkeiが境界に引っかかります。double型の場合8バイト区切りに収まる
ように構造体を作らなければなりません。なのでこの場合

struct CPU {
     char   name[8];
     int    syuuhasuu;
     int    dummy;
     double chokkei;
     double takasa;
};

のようにダミーの要素を追加することでこの問題を回避します。

επιστημη 2003/02/05(水) 09:36:47
え?え? このコンテキストでアラインメントが影響するかしら?

kazuma 2003/02/05(水) 09:59:49
> wood 2003/02/05(水) 05:04:44

Release 版でビルドするとエラーメッセージが出るみたいです。

runtime error R6002
- floating point not loaded

C-FAQ の 14.13 が関係ありそうです。
http://lagendra.s.kanazawa-u.ac.jp/ogurisu/manuals/c/C-faq/C-faq-
00.html#contents

暇人貴子 2003/02/05(水) 10:18:36
私の環境では、単に
#include <stdio.h>

void main(void)
{
  double d;
  scanf("%lf", &d);
}

としても、ランタイムエラーが発生します。

WinMe, VC++6.0SP5

Green 2003/02/05(水) 10:28:27
> え?え? このコンテキストでアラインメントが影響するかしら?
すみません。ちょっと書き方が悪かったですね。
この場合関係ないけど気を付けたほうがいいよということで(^^;
私自身アライメント関係で昔苦労したものでこの問題について過敏になりすぎてまして。

ぱふ 2003/02/05(水) 10:32:57
#include <stdio.h>

void main(void)
{
  float c,d;
  scanf("%f", &d);
  c = d+1.0;
  printf("%f\n",c);
}

こうしたらランタイムエラーは発生しませんでした。

WIN2000SP2 VC++6.0SP4

kazuma 2003/02/05(水) 13:34:05
追加情報です。

http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B37507

kazuma 2003/02/05(水) 14:03:17
kazuma 2003/02/05(水) 09:59:49

の発言についてです。

> Release 版でビルドするとエラーメッセージが出るみたいです。

これだと、「Debug 版ではエラーにならなくて、Release 版だとエラーになる」
というふうに受け取れてしまいますね。

紛らわしいので以下のように訂正します。
「Release 版でビルドすると、
 コンソールにエラー番号とエラーメッセージが表示されました。」

Windows2000 SP3, VC++ 6.0 SP5

c 2003/02/05(水) 17:31:44
>>    struct CPU{
>>        char   name[8];
>>        int    syuuhasuu;
>>        double chokkei;
>>        double takasa;
>>    };

>この場合、chokkeiが境界に引っかかります
これって本当に引っかかるんですか.
>0x0 0x4 0x8 0x10
>※便宜上オフセットで書いています
これって演算処理をしやすいようにコンパイラが意図して
領域を確保しているんじゃないんですか
実際自分が思い描いた領域が確保したいんなら
vc++の場合、構造体メンバのアライメントを1バイトにしたら
確保できますよ
間違っていたらすみません

SSA 2003/02/06(木) 02:31:20
既に解決されてますが、昨年末に別の掲示板でも同様の投稿がありましたので、一応そのリンク
を。
http://forums.belution.com/ja/cpp/000/006/23.shtml

それから、cさんの補足って感じですが…
ユーザが特にアラインメントを指定していない限り、通常、コンパイラは自動的に4バイトや
8バイト境界へのアラインメントを行ってくれます。
よって、ユーザはアラインメントを特に意識することなく、double型などのデータも扱うこと
が出来ます。

# 独自にメモリ管理をやりだすと、自分でしっかり意識しないといけない問題ですが… GCとか

c 2003/02/06(木) 03:17:53
すみませんはずしてましたね
実行して見て意味がわかりました。

古いスレッドには追加発言できません。