>> ctype.hのtoupperという関数についてですが、
>> 引数と戻り値はchar型と思い込んでいたのですが
なぜに。
>> 教科書を読んでみると
>> int toupper(int c);
>> という風にint型でした
intで正解です。toupper(EOF)がEOFを返すと決まっていますので、char型で
はtoupper()の取りうるすべての値を表すことができないのが一般的です
(toupper()にEOFを渡すようなコーディングが一般的かどうかは知らない)。
-----
なぜtoupper()がEOFを引数にとるか、というのはたぶんgetchar()に
あわせてあるんじゃないかと思います。
なぜgetchar()がEOFを返すかといえば、
while ((c = getchar()) != EOF) ...
と書けるように、ということになってます(たとえばK&R2 1.5.1節)。
ではなぜcがcharで済むように
while (c = getchar(), !(feof(stdin) || ferror(stdin))) ...
ではいけなかったのかは、「歴史的な事情」「EOFなら1回の比較ですむ」
などと聞きます。後者に関しては
while (c = getchar(), !eof_or_error(stdin)) ...
とか、
while (getchar(&c)) ...
(成功したかどうかのフラグが戻り値で、成功したときだけ入力文字はcに
入る。これならcはcharでよい)
など、いくつか代案が考えられるので説得力に欠けるように思います。
「歴史的な事情」に関しては、
Dennis M. Ritchieのページ
http://cm.bell-labs.com/cm/cs/who/dmr/
にいろいろおもしろそうな文献があります。
解釈はやめて事実だけ並べると、
7th Edition Unix以降で現在のEOF返しになってます。
6th Edition Unix以前のCではgetchar()はEOF時に'¥0'を返していました。
(char c; c=getchar()といった例がC Reference Manualに載ってます。)
Cの前のBではgetchar()は'*e'(Bでの文字列終端記号。ヌル文字'*0'とは
別だったらしい)を返していました。
「Unix Programmer's Manual, First Edition」(このころはアセンブリ)
では入力文字の入るレジスタとは別のフラグでEOF/エラーを示したことに
なってます。
-----
ちなみに、もともとCで文字'c'はint型です。getchar()がEOFではなく'¥0'
を返す6th Edition UnixのCでも'c'はint型で、char型の値は式中や関数の
引数としてはint型に昇格されます。なぜこうなっているのか不思議ですが
(PDP-11の都合でしょうか? 型なしのBとの互換性? C処理系の実装上の都合?)、
むしろtoupper()がint型なのは(getchar()がintを返すのも)「EOFを表す
必要があるから」じゃなくて、こちらの理由からだと思えます。
--
新崎@東大院総合
ara...@mns2.c.u-tokyo.ac.jp
> (toupper()にEOFを渡すようなコーディングが一般的かどう
> かは知らない)。
MBCSな処理系ではダメですけど、そうでない処理系では
while ((c = toupper(getchar())) != EOF)
みたいな使い方は割と一般的ではないでしょうか。
--
「japan.mailでのメールフレンド募集は止めよう」キャンペーン中
岩太郎 iwa...@rr.iij4u.or.jp
> えっと、引数のほうは「プロトタイプ宣言のない古い C 言語では、
> char にはできない」ってところが究極的な問題だと思います。
>
> #char 型の実引数は int に格上げして渡すのが仕様
そう、仕様ですね。
char c, d;
printf("%d\n", sizeof c );
printf("%d\n", sizeof(c - d) );
char を int にキャストして渡す「べき」なのではなく、
char 変数から値を取り出した時点で格上げは
強制的に行われてしまいます。
EOF との区別のため、という説明も間違ってはいませんが。
<38095005...@mail.ecc.u-tokyo.ac.jp>の記事において
L94...@mail.ecc.u-tokyo.ac.jpさんは書きました。
L94102> #isalpha は実際の関数としても存在しますが、ふつうに使うと
L94102> # #define isalpha(c) (或る表[c] & (2<<定数))
L94102> #でマクロ展開される場合が多いので、上の場合に toupper(c)
L94102> #とすると、「或る表[177]」ではなく「或る表[-79]」という
L94102> #メモリ参照をしてしまうことになります。
L94102> #EOF(==-1) は何とかなるんだろうか
ふつう,
((或る表+1)[c] & 定数)
とか,
(或る表[(c)+1] & 定数)
とかやってませんかね?
そういう理由で, ふつうは EOF == -1 である, と.
--
名古屋大学 工学部 電子工学科 平田研究室
小野 孝男