YuOさん
なるほど、内部がキャラクタベースだったということですね。
ISLeさん
ISLe さんが書きました:
いわゆる変数等の中身がメモリ上にどういうふうに並んでいるかということです。
要するにバイナリデータのことです。
C/C++言語の規格書に載ってます。
オブジェクトの内部表現っていうんですね。
規格書は読んだことが無かったので一度眺めてみます。
ISLe さんが書きました:
char*じゃないと内部表現に1バイトずつアクセスできないじゃないですか。
1バイトずつアクセスするためにchar*なわけですか。
Ryo さんが書きました:
ofs.write((char*)&a,1);
ofsは、char型を取り扱うように宣言されているbasic_ofstreamですから
第2引数に1を指定してあれば、sizeof(char)×1分のみを扱うということになります。
int a = 10は、内部的には 0a 00 00 00 ですから、
writeもreadでも、先頭の0aのみが読み書きされます。
これが、ucharの範囲分しか正常に扱えない理由です。
ofs.write((char*)&a,sizeof(int) * 1);
とすれば、int a を1個分扱うことはできます。
すみません質問の仕方を間違えたみたいです。
uchar(符号無し)の理由を知りたかったのです。
その説明だけではcharの範囲を扱ってるのではないのでしょうか?
例えば、int型の-1のビット表記は
11111111 11111111 11111111 11111111
ですよね。
そしてchar型分確保するので
11111111
これはchar型では-1
そして、readで取り出されます。
11111111
つまりchar型の-1バイト。
しかし実際には、書き込み取り出すと符号が無くなり
255になります。
この仕組みが分からないので質問させて頂きました。
・・・・と、此処まで書き込んでようやく気付きました。
11111111
が
int だから
00000000 00000000 00000000 11111111
こうなるからですね。
つまり、charならちゃんと-1になりますね。
(負数のキャスティングの際はコンパイラ?が自動的に変換しているのでしょうかね)
Ryo さんが書きました:
ちなみにfwriteの場合、const void*でデータバッファを渡すように宣言されていますが、
VS2008でソースをおっかけると 内部で_fwrite_nolock()を呼び出しており、
その中で、const char*にキャストしてから書き込んでいます。
なるほど1バイト単位でアクセスできるcharを使い、渡されたサイズずつ書き込んでいるわけですね。
Ryo さんが書きました:
もしかすると、
「void*は、型がないため素のポインタっぽいので、色んな型・サイズを扱う基礎的なものはvoid*のほうが似合う
逆にchar*はcharが文字ゆえ、整数型の変数のポインタとして利用するのは違和感がある」
と、いうような感じ方をされているのでしょうか?
上は概ねそのとおりです。
void であればどんな型でもアドレスとして確保できるため(サイズはありませんが)、汎用的な処理には便利であると思っています。
下に関してはそうは思っていません、char型は文字では無く実際には1バイトの整数型ですから。
Cでは出力等の最、整数を文字に変換するだけですから、int型でも良いはずです。
(charの方が使いやすいし特化されてます、それにデバッガで追いかけたとき分わかり難いので当然使いませんが)
なので整数型の変数のポインタとして利用するのは違和感があるわけではありません。
理由が分からないと正しく使えないからです。
理由が分からないと理解できませんし、理解していないのに応用するのは普通は無理です。
かずまさん、Ryoさん、ISLeさん、YuOさん
丁寧に説明して頂き有難うございました。
概ね理解できたので解決とさせて頂きます。