いずれも戻り値、引数の指定がint型なのにchar型の配列の要素を渡すことができるのは何故なのでしょうか?
ご教授お願いします
toupper()関数やtolower()関数について
Re: toupper()関数やtolower()関数について
環境はよくわかりませんが、VisualStudio2010で以下のコードを組んだところキャストエラーがまず起きます。
次に
と書いたところ、コンパイルがとおり、(何故か)文字列が表示されました。
ただし、元の"abc"のままでしたが
環境がわからないのでなんともいえないのですが、
文字列はマルチバイトの場合charのポインタ型で、ポインタはintと同じ32bitなので
コンパイラがポインタをintに勝手に変換した可能性はあります。
#include <stdio.h>
#include <ctype.h>
int main()
{
char* p = "abc";
printf_s("%s\n",toupper(p));//ここでchar*からintへの変換ができません。
}
ただし、元の"abc"のままでしたが
環境がわからないのでなんともいえないのですが、
文字列はマルチバイトの場合charのポインタ型で、ポインタはintと同じ32bitなので
コンパイラがポインタをintに勝手に変換した可能性はあります。
Re: toupper()関数やtolower()関数について
夕月さん、ハッカーさん返答ありがとうございます!!
なるほど、整数の格納範囲においてchar型はint型の部分集合ということですか
納得です!!
なるほど、整数の格納範囲においてchar型はint型の部分集合ということですか
納得です!!
Re: toupper()関数やtolower()関数について
ん?しかしchar型が英字を扱える以上、完全な部分集合とは言えませんよね?
あくまで整数範囲に限っては、と注釈がついてしまいます
そういう場合でもint型指定の中でchar型を扱ってもいいんでしょうか?
理解が悪くて申し訳ないです
あくまで整数範囲に限っては、と注釈がついてしまいます
そういう場合でもint型指定の中でchar型を扱ってもいいんでしょうか?
理解が悪くて申し訳ないです
Re: toupper()関数やtolower()関数について
厳密なことを言うと、toupper 関数の int型の引数に char型配列の要素を渡すことは規格違反です。やまだ さんが書きました:いずれも戻り値、引数の指定がint型なのにchar型の配列の要素を渡すことができるのは何故なのでしょうか?
最新の規格は ISO/IEC 9899:2011 (通称C11)ですが、JIS は JIS X3010:2003 で、
これは ひとつ前の ISO/IEC 9899:1999 (C99) です。
toupper などの <ctype.h> に属する関数に関してはどれをみても同じなので、
C99 から引用してみます。
7.4 Character handling <ctype.h>
The header <ctype.h> declares several functions useful for classifying and mapping
characters.166) In all cases the argument is an int, the value of which shall be
representable as an unsigned char or shall equal the value of the macro EOF. If the
argument has any other value, the behavior is undefined.
または EOF の値に限られていて、それ以外だど動作は未定義となっています。
値の範囲というのは処理系定義ですが、私たちが普段使うコンパイラでは、
unsigned char は 0~255、EOF は -1 です。
すなわち、toupper の引数は intですが、-1~255 の値しか渡してはいけません。
ところが、char の範囲は -128~127 が一般的です。
char をそのまま引数に使うと -128~-2 の値に対しては、動作が未定義となります。
具体例をあげると、Shift-JIS で半角カタカナの 'ア' は 0xb1 ですが、これを char型の
変数に入れるとその値は -79 です。
toupper でググって、そこに出てきたサイトのサンプルプログラムを見ると、ほとんど
すべてが toupper に char を渡しています。それでうまくいくのは、渡しているの文字が
7ビット ASCII の文字だけだからです。
あるいは、toupperの実装が、未定義の動作に対して、うまく処理をして、本当に
小文字である場合以外は、元の引数の値を返すようになっているのかもしれません。
夕月さんの無茶苦茶なプログラムも、ポインタを int に変換して、とんでもない値を
toupper に渡しているのに、それは小文字の範囲外なので、元のポインタの値がそのまま
返ってきて、文字列が表示されているのでしょう。
Re: toupper()関数やtolower()関数について
ctype.h関数以外にも、strchr関数の第2引数、printf関数の%cに対応する引数もint型です。
また、Cでは、文字定数('A'など)もint型です。
また、Cでは、文字定数('A'など)もint型です。