Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

toupper

31 views
Skip to first unread message

tsukasa

unread,
Oct 12, 1999, 3:00:00 AM10/12/99
to
初歩的なことです。
ctype.hのtoupperという関数についてですが、
引数と戻り値はchar型と思い込んでいたのですが
教科書を読んでみると
int toupper(int c);
という風にint型でした
別にchar型を入れてうまく行くので別に問題はないのですがやっぱり気になるの
でどなたかお願いします。


Yasuki Arasaki

unread,
Oct 13, 1999, 3:00:00 AM10/13/99
to
In article <7tvf7a$27e$1...@nntp.tiki.ne.jp>
"tsukasa" <tsu...@mx3.tiki.ne.jp> さんwrote:

>> 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

岩太郎

unread,
Oct 13, 1999, 3:00:00 AM10/13/99
to
Yasuki Arasakiさんの<38037C...@mns2.c.u-tokyo.ac.jp>から

> (toupper()にEOFを渡すようなコーディングが一般的かどう
> かは知らない)。

 MBCSな処理系ではダメですけど、そうでない処理系では

while ((c = toupper(getchar())) != EOF)

みたいな使い方は割と一般的ではないでしょうか。

--
 「japan.mailでのメールフレンド募集は止めよう」キャンペーン中
 岩太郎 iwa...@rr.iij4u.or.jp

Yoshiki Kataoka

unread,
Oct 18, 1999, 3:00:00 AM10/18/99
to
片岡です。

> えっと、引数のほうは「プロトタイプ宣言のない古い C 言語では、
> char にはできない」ってところが究極的な問題だと思います。
>
> #char 型の実引数は int に格上げして渡すのが仕様

 そう、仕様ですね。

char c, d;
printf("%d\n", sizeof c );
printf("%d\n", sizeof(c - d) );

char を int にキャストして渡す「べき」なのではなく、
char 変数から値を取り出した時点で格上げは
強制的に行われてしまいます。

EOF との区別のため、という説明も間違ってはいませんが。

Takao Ono

unread,
Oct 18, 1999, 3:00:00 AM10/18/99
to
小野@名古屋大学 です.

<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 である, と.
--
名古屋大学 工学部 電子工学科 平田研究室
小野 孝男

0 new messages