データ型を知ろう

C言語のデータ型

Windows APIを使うとなると、通常はHSPで使われないようなC言語の知識がどうしても必要になる部分が出てきてしまいます。この『データ型』もそういったものの1つです。

データ型とは、データの性格や数値の表現範囲などを規定するためのものです。すなわち、データのサイズや符号の有無、データが変更されるものかどうかを規定します。HSPでは符号付き32ビット整数と文字列の2種類が使われていますが、C言語では多くの型が存在します。(実際には、HSP3からいくつかの拡張変数型や拡張プラグイン定義型が追加されていますが、ここでは考えないことにします。)

まず、Cの世界では最も基本的な型として以下のものがあります。(32ビット処理系の場合)

データ型 ビット幅 呼称 範囲
文字型 char 8 文字型 -128127
unsigned char 8 符号なし文字型 0255
整数型 short (int) 16 符号付き短長整数型 -3276832767
unsigned short (int) 16 符号なし短長整数型 065535
int 32 符号付き(倍長)整数型 -21474836482147483647
long (int)
unsigned (int) 32 符号なし(倍長)整数型 04294967295
unsigned long (int)
浮動小数点数型 float 32 単精度実数型 およそ10-381038(有効数字7桁)
double 64 倍精度実数型 およそ10-30810308(有効数字15桁)
型なし void - - -

データ型の中で ( ) で括った部分は省略可能です。

int型やunsigned int型のデータサイズは、16ビット環境では16ビット(2バイト)ですが、32ビット環境では32ビット(4バイト)になります。


さらに、上で示した基本データ型にアスタリスク("*")をつけたものは、そのデータ型へのポインタ(メモリアドレスを格納する変数)を表します。たとえば、「unsigned int*」は「unsignd int」型データへのポインタ、すなわち、「unsignd int」型の変数のアドレスを格納する変数の型を表しています。

また、データ型の先頭に「const」をつけると、それはデータの内容が変更されないことを示します。

さらに、C言語では、『構造体』や『共用体』などといった、任意に定義可能なデータ型も存在します。特に構造体はWindows APIを使う上で欠かせない事柄ですので、これについては後で詳細に述べることにします。


さて、Windows APIを使うプログラミングではこう言ったデータ型に別名をつけて、いろいろなデータの種類をわかりやすく表すようにしています。たとえば、「unsigned short int」に「WORD」という別名をつけて、それを1つの型として扱っています。他にも、「char*」を「LPSTR」としたりしています。以下にWindows APIで使われる代表的なデータ型の一部を挙げておきます。あくまで参考として挙げているので、すべてを覚える必要などはありません。

データ型 意味
BOOL TRUE1と定義)またはFALSE0と定義)のブール値。通常はFALSEであるかFALSE以外であるかで識別する。
BOOLEAN TRUE1と定義)またはFALSE0と定義)のブール値。通常はFALSEであるかFALSE以外であるかで識別する。(1バイト)
BYTE 8ビット符号なし整数(unsigned char型/1バイト)
CHAR 文字型(char型/1バイト)
COLORREF カラー値
DWORD 32ビット符号なし整数(unsigned long型 )
HWND ウィンドウハンドル
HDC デバイスコンテキストハンドル
HICON アイコンハンドル
HANDLE オブジェクトハンドル
HBITMAP ビットマップハンドル
HBRUSH ブラシハンドル
HCURSOR カーソルハンドル
HGDIOBJ GDIオブジェクトハンドル
HGLOBAL グローバルオブジェクトハンドル
HIMAGELIST イメージリストハンドル
HINSTANCE インスタンスハンドル
HMENU メニューハンドル
INT 符号付き整数(int型)
LANGID 言語ID(WORD型/2バイト)
LCID ロケールID(DWORD型/4バイト)
LONG 32ビット符号付き整数(long型)
LONGLONG 64ビット符号付き整数(__int64型/8バイト)
LPARAM 32ビットメッセージパラメータ
LPBOOL/PBOOL BOOL型へのポインタ
LPBYTE/PBYTE BYTE型へのポインタ
LPCSTR/PCSTR 定数ANSI(またはマルチバイト)文字列へのポインタ。(内容が変更されない)
LPCTSTR/PCTSTR ANSI版では定数ANSI(またはマルチバイト)文字列へのポインタ。Unicode版では定数ワイド文字列(Unicode文字列)へのポインタ。(内容が変更されない)
LPCVOID あらゆる型のデータへのポインタ。(内容が変更されない)
LPCWSTR/PCWSTR 定数ワイド文字列(Unicode文字列)へのポインタ。(内容が変更されない)
LPDWORD/PDWORD DWORD型へのポインタ
LPHANDLE/PHANDLE HANDLE型へのポインタ
LPINT/PINT INT型へのポインタ
LPLONG/PLONG LONG型へのポインタ
LPSTR/PSTR ANSI(またはマルチバイト)文字列へのポインタ
LPTSTR/PTSTR ANSI版ではANSI(またはマルチバイト)文字列へのポインタ。 Unicode版ではワイド文字列(Unicode文字列)へのポインタ。
LPVOID/PVOID あらゆる型のデータへのポインタ
LPWORD/PWORD WORD型へのポインタ
LPWSTR/PWSTR ワイド文字列(Unicode文字列)へのポインタ
PBOOLEAN BOOLEAN型へのポインタ
SHORT 16ビット符号付き整数(short型/2バイト)
TCHAR ANSI版ではCHAR型(1バイト)。Unicode版ではWCHAR型(2バイト)。
UINT 符号なし整数(unsigned int型)
ULONG 32ビット符号なし整数(unsigned long型)
ULONGLONG 64ビット符号なし整数(unsigned __int64型/8バイト)
VOID 型なし(void型)。
WCHAR 16ビットワイド文字(Unicode文字)(2バイト)
WORD 16ビット符号なし整数(unsigned short型/2バイト)
WPARAM 32ビットメッセージパラメータ

重要なのはデータ型のサイズ

HSPでWindows APIを扱う場合には、データ型そのものは実はあまり問題になりません。問題となるのは、その型の表すデータのサイズなのです。たとえばCHAR型は8ビット(1バイト)であるとか、WORD型は16ビット(2バイト)であるといったことです。上の表で示したデータ型のデータサイズは、明示しているもの以外はすべて32ビット(4バイト)になります。Windowsは32ビット環境であるために、すべてのオブジェクトのハンドルは32ビット(4バイト)の大きさになりますし、ポインタに関しても、すべて32ビット仮想アドレスで表されているのでどのポインタも32ビット(4バイト)の大きさになります。(ちなみに、64ビット環境ではハンドルやポインタは64ビットになります。)

で、なぜこれらのサイズが問題になるのかというと、たとえばWORD型データ(サイズ2バイト)の配列をHSPで扱う場合を考えてみましょう。HSPの数値変数のサイズは4バイトであるために、スクリプト中で普通に

a = 100, 222, 314, 5413, ……

と代入したのでは、WORD型の配列としては

100, 0, 222, 0, 314, 0, 5413, 0, ……

のようになってしまうのです。これでは期待したとおりの結果が得られなくなってしまうでしょう。WORD型の配列で

100, 222, 314, 5413, ……

とするためには、

a(0) = 100 + ( 222 << 16)     ; "+"を"|"にしてもよい
a(1) = 314 + (5413 << 16)

としなくてはならないのです。そのデータ型のデータサイズがいくらかを知ることがHSPでAPIを使っていく上では非常に重要になってきます。