C/C++言語は動作するプラットフォームによって姿を変える。さながらカメレオンのように動作するプラットフォームの色に染まるのだ。クロスプラットフォームで動作するネイティブプログラムで特に苦労するのは、微妙にいろいろ型が異なることだ。
例えは以下のサイトにあるような大量のtypedef...typedef...
ここの表をちょっと写させてもらう
データ型 - Win32 API 階梯
C の型 | Win32 API での別名 |
---|---|
char | CHAR |
unsigned char | BYTE |
short | SHORT |
unsigned short | WORD |
int | INT |
unsigned int | UINT |
long | LONG |
unsigned long | DWORD / ULONG |
float | FLOAT |
double | DOUBLE |
void | VOID |
void * | HANDLE |
例えばBYTEならば、ソースコードに以下のように書くとLinuxでも同じことが出来る。
typedef unsigned char BYTE;
そして素のC/C++にはBYTEという型はない。BYTEは幻術だったのだ…
だからJavaのbyteクラスとWindowsのtypedefのBYTEは全く別物だ。
プラットフォームごとのサイズの違い
型のバイト数はプラットフォームによって異なる。調査したものだけここに載せる(あくまで参考レベル)
C の型 | Win32 API での別名 | Linux x86_64 | Mac OS X x86_64 | Win32 |
---|---|---|---|---|
char | CHAR | 1BYTE | 1BYTE | 1BYTE |
unsigned char | BYTE | 1BYTE | 1BYTE | 1BYTE |
short | SHORT | 2BYTE | 2BYTE | 2BYTE |
unsigned short | WORD | 2BYTE | 2BYTE | 2BYTE |
int | INT | 4BYTE | 4BYTE | 4BYTE |
unsigned int | UINT | 4BYTE | 4BYTE | 4BYTE |
long | LONG | 8BYTE | 8BYTE | 4BYTE |
unsigned long | DWORD / ULONG | 8BYTE | 8BYTE | 4BYTE |
float | FLOAT | 4BYTE | 4BYTE | 4BYTE |
double | DOUBLE | 8BYTE | 8BYTE | 8BYTE |
void | VOID | - | - | - |
void * | HANDLE | - | - | - |
C++特有のキャスト方法
説明は詳しい人にしてもらうのがいい
C++のキャスト方法が詳しく書かれている
C++編(言語解説) 第24章 C++独自のキャスト
C言語のキャストとC++のキャストの比較
本の虫: 邪悪なC形式のキャストにしかできないこと
型変換で必要なのは2つstatic_castとreinterpret_castだ。
・static_castは単純な型から型への変換(ex: long -> int)
・reinterpret_castはポインタを使う変換だ(ex: wxString(reinterpret_cast
こっちは使い方が難しい。まあポインタ使うやつがreinterpret_castで、使わないほうがstatic_castみたいなノリで。
BYTEをWORDにキャスト
ありえないキャスト?ノンノン、知らないだけ
wandboxっていうオンラインコンパイラがあるらしいんすよぉ…
[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ
#include <iostream> #ifdef _WIN32 #include <Windows.h> #else typedef unsigned short WORD; typedef unsigned char BYTE; #endif int main() { // サイズはナンボ? std::cout << sizeof(BYTE) << std::endl; std::cout << sizeof(WORD) << std::endl; // なんか文字列が入ってるやつを変換 BYTE aquei[] = {0xe9, 0x98, 0xbf, 0xef, 0xbc, 0xb1, 0xe6, 0xad, 0xa3, 0xe4, 0xbc, 0x9d , 0x00 }; // Windows使ってる方は最初からバイナリをShift_JISで定義するといいよ // BYTE aquei[] = {0x88,0xa2,0x82,0x70,0x90,0xb3,0x93,0x60, 0x00}; // const char* 型に変換できる。やったぜ。 // &をつけると先頭のポインタを渡せる const char* str = reinterpret_cast<const char*>(&aquei); puts(str); // 10進数で19800を16進にすると下記の通り // BYTE number[] = {0x4D, 0x58}; // <= リトルエンディアンなので左は間違い BYTE number[] = {0x58, 0x4D}; // <= 逆からブチ込んでいくスタイル WORD* w = reinterpret_cast<WORD*>(&number); std::cout << *w << std::endl; return 0; }
出力
Start 1 2 阿Q正伝 19800 0 Finish
動作検証環境
・Debian GNU/Linux (7.3), GCC-4.6ぐらい
・Windows 7 64bit, Visual Studio 2012 Express Edition