許せない心理テスト

細々と半年ほど柴田望洋氏の「明解C言語 入門編」でC言語の勉強をしております。

最近構造体について勉強しはじめ、プログラム実行時の日付を出力するプログラムがテキストに載っていて、以下がその関数です。


void put_date(void)
{
time_t current;
struct tm *local;
char wday_name[][3] = { "日", "月", "火", "水", "木", "金", "土" }; /*-- [][3]?? --*/

time(&current);
local = localtime(&current);
printf("%4d年%02d月%02d日(%s)", local->tm_year + 1900, local->tm_mon + 1, local->tm_mday, wday_name[local->tm_wday]);
}


これの曜日を格納する配列wday_name[][3]は、どうしてこのような宣言をするのでしょうか?
wday_name[][7]にすると何か間違っているのですか? 自分で後者の方で実行してみたところ、特に動作に違いは見られませんでした。
どうぞよろしくお願い致します。

A 回答 (6件)

wday_name[][3]


としているのは各曜日をあらわす文字が3つで足りるからです。
漢字1文字でchar2つ分、それに文字列の終わりを示すNULL文字を追加して合計3つです。
wday_name[][7]としても違いが無いのは、7つ分確保して残りの4つ分を利用していないからです。

この宣言を省略せずに書けば、
wday_name[7][3]
となります。この場合charが3つ分の領域をもつ配列を7個分確保していることとなります。
    • good
    • 0
この回答へのお礼

素早い回答どうもありがとうございます。
なるほど、3というのは配列の大きさを定義しているのですね。7にしても動作が同じなのは当然ですね。
逆に2以下にした時はちゃんと動作しなかったのもこれで納得がいきました。

お礼日時:2006/09/27 09:13

いっそ


char wday_name[][3]=

char *wday_name[]=
にする
    • good
    • 0
この回答へのお礼

ポインタの方からアプローチするというやり方もあるんですね。
プログラムとしてはどちらが良いものになるんでしょう?
後者でポインタを駆使してやってみるのも面白そうです。

お礼日時:2006/09/27 09:33

質問に対する直接の回答は既に出ていますので、ちょっと異なる視点から書いてみます。



曜日を表す各文字("日"など)が何バイトになるかは処理系に依存します。ですから、より厳密に記述するには、wday_name[][3]ではなく、wday_name[][MB_LEN_MAX+1]としなければなりません。

MB_LEN_MAXは多バイト文字の最大バイト数であり、終端のナル文字のために+1しています。バイト数自体はMB_CUR_MAXでもよいのですが、MB_CUR_MAXは定数式にはならないので配列の要素数には使えません。
    • good
    • 0
この回答へのお礼

なるほど、こちらの方が処理系に依存せずより良いプログラムになりますね。
文字が何バイトになるのかは処理系によって違うというのは驚きました。

お礼日時:2006/09/27 09:28

wday_name[][3]の[3]は、1つの曜日を格納するサイズです。

これは、漢字1文字=2バイト+終端NULLの1バイトで、計3バイトとなります。最初の[]は、[7]とかいてもよいですが、要素を宣言された分、コンパイラが確保しますので、[]と記述しても[7][3]と同じ事になります。
たぶん、貴方は、[3]を[7]にしたのは、曜日の数が7だであるからそうしたのでしょうが、[7]にすべきは、
最初の[]であって、2番目の[]ではありません。
もし、[][7]とすると、この場合は、[7][7]と同じ事になります。最初の[7]が要素の数(曜日の数)、2番目の[7]は、最低[3]以上であればよいので、[7]でも正しく動きます。もちろん、[][256]で、問題なく動きます。
    • good
    • 0
この回答へのお礼

はい、どうやら逆に理解をしていたようです。
wday_name[][3]を見た時、「格納する曜日が7つあるのになんで3なんだろう?」と頭をひねっていました。
わかりやすい解説をどうもありがとうございました。

お礼日時:2006/09/27 09:22

>char wday_name[][3]


この定義は配列の配列。

先頭の[]は、初期化時において配列要素数をコンパイラに数えさせる記述。

後ろの[3]は、本来の型(char)の要素数。
おそらくマルチバイト環境下で曜日を示す漢字(例えば"日")を
格納するのに十分なサイズがchar*2なのでしょう。
2 + 1(0x00) = 3。

つまり、あなたの定義wday_name[][7]は、
3バイトで十分なものを7バイト確保する定義となったに過ぎません。
余分に確保しただけなので動作は変わらないはず。
間違いではないが、無駄。
    • good
    • 0

曜日を格納する配列のサイズを3バイトで定義しています。


3を7に変えても変化がないのは、7バイトの領域に曜日が格納されるため動作に変化がないのです。

定義する内容がハッキリしているのなら
wday_name[6][3] /* 0~6の7要素 */
としても言いわけです。
    • good
    • 0
この回答へのお礼

そうですね、この場合曜日を格納すると目的がはっきりしているので
最初からwday_name[7][3]という風に定義しても良いですね。

お礼日時:2006/09/27 09:16

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


おすすめ情報