6: 2007-03-22 (木) 19:20:56 |
7: 2007-03-22 (木) 23:44:32 |
| C言語では大体こんな感じ。 | | C言語では大体こんな感じ。 |
| | | |
- | |int型|整数|4バイト|どうも通常は動作している環境って単位みたい。つまり16bitCPUなら16bit、32bitCPUなら32bitとか(Cコンパイラに依存?)| | + | |
- | |float型|小数|4バイト|文字通り少数を扱いたい場合使うらしい| | + | |型名|バイト数|用途|範囲(10進数)|範囲(16進数)|備考|h |
- | |char型| 文字(一文字単位)|1バイト|「A」だの「i」だの| | + | |char型|1バイト|文字(一文字単位)|-127〜127|0x00〜0xFF|「A」だの「i」だの「#」だの| |
- | |double型|少数|8バイト|より桁数が多い少数?| | + | |short型|2バイト|すこし大きな整数|-32768〜32767|0x0000〜0xFFFF|| |
- | |ポインタ型|4バイト|アドレス変数|アドレスを記憶する| | + | |long型|4バイト|かなり大きな整数|-214783648〜214783647|0x00000000〜0xFFFFFFFF|| |
| + | |int型|4バイト|かなり大きな整数|-214783648〜214783647|0x00000000〜0xFFFFFFFF|どうも通常は動作している環境って単位みたい。つまり16bitCPUなら16bit、32bitCPUなら32bitとか(Cコンパイラに依存?)| |
| + | |float型|4バイト|少数を扱える|少数を扱いたい場合使うらしい||| |
| + | |double型|8バイト|より桁数が多い少数|||| |
| + | |ポインタ型|4バイト|アドレス変数|アドレスを記憶する||| |
| | | |
| ・・・こうして見ると、intやfloat、ポインタはみな同じバイト数である。なのでおそらく、実際にメモリ内に記憶されている状態ではまったく同じ状態だと思われる。 | | ・・・こうして見ると、intやfloat、ポインタはみな同じバイト数である。なのでおそらく、実際にメモリ内に記憶されている状態ではまったく同じ状態だと思われる。 |
| -COLOR(blue){もちろん、 i = (int)c + (int)z; と書いても当然エラーにはなりません。むしろこれが正しいのです。''本来の概念''で言えば。} | | -COLOR(blue){もちろん、 i = (int)c + (int)z; と書いても当然エラーにはなりません。むしろこれが正しいのです。''本来の概念''で言えば。} |
| | | |
- | もちろん「許容」にもちゃんと法則があります。これには順番があります。以下を順番に適用していくのです。 | + | もちろん「許容」にもちゃんと法則があります。 |
- | -最後は左辺の型に自動調整される | + | ~ |
| + | 許容の法則は一般にちょっとややこしい説明がされていることが多いのですが、こんな風に分けて考えればそうむずかしくありません。 |
| | | |
| | | |
- | です。 | + | まず、左辺と右辺に分けて考えるといいです。 |
| + | -まず右辺内 |
| + | ++混在する一番大きな型に合わせて自動調整される |
| + | ++ただし、int以下のものは全てintに強制変換される |
| + | ++以上の法則で、「とりあえず右辺内」の値が出来上がる |
| + | -次に左辺 |
| + | ++右辺の値や型がなんだろうと左辺の型に強制変換される |
| + | ++もしはみ出た場合は切り捨てられる |
| | | |
- | こんな式を妄想してみます。 | + | 基本的にはこれを上から順番に行い、最後に左辺の値が決まると考えてもらってOKです。 |
| + | |
| + | 実際の場合を思考実験してみましょう。たとえばこんな式の場合。 |
| | | |
| char c; | | char c; |
| int i; | | int i; |
- | short s; | |
- | double d; | |
| | | |
- | c = 0x11; | + | c = 0xf3; |
- | i = 0x22; | + | i = 0x12; |
- | s = 0x33; | + | |
- | d = 0x44; | + | c = c + i; |
| + | |
| + | printf("data is 0x%X\n",c); |
| + | |
| + | これは暗算できますね?。答えは0x105になるはずです。しかしこれを実際にコンパイルして実行すると、答えは0x5になります。はて??? |
| + | |
| + | c = c + i; /* ← ここがどう処理されているのか? */ |
| + | |
| + | ++まず右辺。 |
| + | ++おぉ? iはintだけど、cはcharじゃないか!。型が違うぞ! |
| + | ++仕方がない。自動的に許容しよう。 |
| + | ++右辺で一番大きいのは・・・int型(変数i)だな! |
| + | ++よし、全ての変数を無理やりint型として考えよう! |
| + | ++結果、この式は、c = 0x000000f3(int型。4バイト) + 0x00000012 (int型。4バイト)に変換だ! |
| + | ++よし!計算できたぞ!。結果はこうだ! c = 0x00000105(int型。4バイト) だ!。 |
| + | ++これで右辺は終了だ!。今度は左辺への代入処理だ! |
| + | ++左辺への代入の場合、右辺が何だろうと左辺の型に強制変換だ! |
| + | ++むむむ! なんていうことだ! 左辺はchar型。右辺はint型。左辺の型のほうが小さいぞ! |
| + | ++・・・しかし、「右辺が何だろうと左辺の型に強制変換」は決まっている!。これは崩せない! |
| + | ++仕方がない。はみ出す部分は残念だが''切捨て''てしまおう! |
| + | ++右辺をこう切り捨てる。 c = 0x05 (右辺の頭の3バイトが切り捨てられた) |
| + | ++よし! 左辺 c に代入できるぞ。代入! |
| + | |
| + | こういう内部処理が行われて、結果、暗算の結果である0x105は0x05に切り捨てられ、cに代入が完成し、計算が終わるのです。 |
| + | |
| + | |
| + | この、自動型調整はややこしいといわれますが、とにかくポイントは、上記の8番の部分。''「式の処理は、一旦右辺の中で全部解決して、それが終わったら改めて左辺への代入に移る」''というところでしょうか? |
| | | |
- | i = c + i + s + d; | + | -COLOR(blue){少数の場合はどうなるの???} |
| + | -COLOR(red){・・・いや申し訳ない。少数を扱う場合も勉強してみたのですが、どうも整理しきれませんでした。またここはオイラが''OSを作る''ために勉強して整理しているサイトなので、このページとしては少数型はこれ以上はツッこまないことにしようかと・・・} |
| | | |
- | printf("data is 0x%x\n",i); | |
| | | |
- | さあ、この計算は型が混在もいいところですね。でもエラーは出ません。Cコンパイラが「許容」しているためです。 | + | *現実の型キャスト(ポインタ) [#j3516d0b] |