くまくまの業務日誌

Markdown記法で徒然に書いてみましょう。

Windowsの型定義情報

WindowsC/C++言語の標準的な型をほぼ使用していません。

Windows開発でよく使う型の情報は以下のようになっています。

■8bit

typedef char CHAR;
typedef char TCHAR, *PTCHAR;
typedef char CCHAR;
typedef char *PSZ;

typedef unsigned char UINT8, *PUINT8;
typedef unsigned char UCHAR;
typedef unsigned char BYTE;
typedef unsigned char *LPBYTE;
typedef unsigned char *PBYTE;
typedef unsigned char uint8_t

16bit、32bit以降は現在環境がないため、後日記載。

■便利(と思われる)マクロ

■■min()、max()は既に宣言済み

NOMINMAX宣言がない場合、以下のマクロが使用可能。

#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif

#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif

■■WINDOWSの最大パス長は260まで

#define MAX_PATH 260

■■BOOL変数の実態はintである。

BOOL変数に設定するのは以下の2つ。

#define FALSE 0
#define TRUE  1

■■コードには影響しないが、可読性が上がるマクロ

void hogehoge(
   IN int input,
   OUT int& response,
   OPTIONAL OUT LPVOID lpvResult);

のように、引数の方向を(無害に)示すことができる。

#define IN
#define OUT
#define OPTIONAL

■■いまや、near far は無意味である。

#define far
#define near

https://docs.microsoft.com/ja-jp/cpp/cpp/stdcall?view=vs-2019

Stdcall呼び出し規約は、Win32 API 関数を呼び出すために使用されます。
呼び出し先がスタックを消去するので、コンパイラによって vararg 関数が
cdeclされます。
この呼び出し規則を使用する関数には、関数プロトタイプが必要です。
__Stdcall修飾子は Microsoft 固有です。

#define CALLBACK    __stdcall
#define WINAPI      __stdcall
#define APIENTRY    WINAPI
#define APIPRIVATE  __stdcall
#define PASCAL      __stdcall

https://docs.microsoft.com/ja-jp/cpp/cpp/stdcall?view=vs-2019

cdeclは、C および C++ プログラムの既定の呼び出し規約です。
スタックは呼び出し元によってクリーンアップされるため、機能をvararg実行できます。
cdecl呼び出し規約では、各関数呼び出しにスタック クリーンアップ コードを含める必要があるため、
stdcallよりも大きな実行可能ファイルが作成されます。 次の一覧は、この呼び出し規約の実装例を示しています。
cdecl修飾子は、マイクロソフト固有です。

#define WINAPIV __cdecl

検索しても、ほとんど見つからない。

□検索条件  "WINAPIV"
検索対象       *.*
フォルダ       C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0
除外ファイル   *.msi;*.exe;*.obj;*.pdb;*.ilk;*.res;*.pch;*.iobj;*.ipdb
除外フォルダ   .git;.svn;.vs
    (サブフォルダも検索)
    (英大文字小文字を区別する)
    (正規表現:bregonig.dll Ver.4.20 with Onigmo 6.2.0)
    (文字コードセットの自動判別)
    (一致した行を出力)


C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\shared\minwindef.h(118,9)  [UTF-8]: #define WINAPIV     CDECL
C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\shared\minwindef.h(129,9)  [UTF-8]: #define WINAPIV     __cdecl
C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\shared\minwindef.h(136,9)  [UTF-8]: #define WINAPIV
C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um\celib.h(172,5)  [UTF-8]: int WINAPIV ceDbgPrintf(BOOL fDebug, char const *pszfmt, ...);
C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um\t2embapi.h(139,24)  [UTF-8]: typedef unsigned long( WINAPIV *READEMBEDPROC ) ( void*, void*, const unsigned long );
C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um\t2embapi.h(140,24)  [UTF-8]: typedef unsigned long( WINAPIV *WRITEEMBEDPROC ) ( void*, const void*, const unsigned long );
C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um\Vfw.h(59,17)  [UTF-8]: #define VFWAPIV WINAPIV
C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um\WinUser.h(325,1)  [UTF-8]: WINAPIV
C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um\WinUser.h(332,1)  [UTF-8]: WINAPIV
9 個が検索されました。

■■ビット操作マクロ

BYTE変数2つからWORD変数を作ったり、WORD変数2つからLONG変数を作ったりするときに使用する。逆のLONGから上半分、下半分を抽出するマクロもある。

Windowsのメッセージ系API(PostMessageやGetMessage、SendMessageなど)で活用していた。 今、この関数を使う人は少ないと思われる。

#define MAKEWORD(a, b)      ((WORD)(((BYTE)(((DWORD_PTR)(a)) & 0xff)) | ((WORD)((BYTE)(((DWORD_PTR)(b)) & 0xff))) << 8))
#define MAKELONG(a, b)      ((LONG)(((WORD)(((DWORD_PTR)(a)) & 0xffff)) | ((DWORD)((WORD)(((DWORD_PTR)(b)) & 0xffff))) << 16))
#define LOWORD(l)           ((WORD)(((DWORD_PTR)(l)) & 0xffff))
#define HIWORD(l)           ((WORD)((((DWORD_PTR)(l)) >> 16) & 0xffff))
#define LOBYTE(w)           ((BYTE)(((DWORD_PTR)(w)) & 0xff))
#define HIBYTE(w)           ((BYTE)((((DWORD_PTR)(w)) >> 8) & 0xff))

■■各変数の最小値、最大値は既に宣言されている。

流石に、32Bitまで。

#define MINCHAR     0x80        
#define MAXCHAR     0x7f        
#define MINSHORT    0x8000      
#define MAXSHORT    0x7fff      
#define MINLONG     0x80000000  
#define MAXLONG     0x7fffffff  
#define MAXBYTE     0xff        
#define MAXWORD     0xffff      
#define MAXDWORD    0xffffffff  

■■64Bit変数は、__int64がプリミティブ宣言

大半はtypedefされたものを使用する。

typedef unsigned __int64 size_t;
typedef __int64 LONGLONG;
typedef unsigned __int64 ULONGLONG;

■■64bit化させるための構造体もある

WIN32APIとしては、こちらが、多用される。
例えば、QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCounter)など。
演算は.QuadPartでまとめたものを使います。数値が小さいはずだからと、LowPartだけで演算しようとすると、痛い目に遭います。

typedef union _LARGE_INTEGER {
  struct {
    DWORD LowPart;
    LONG  HighPart;
  } DUMMYSTRUCTNAME;
  struct {
    DWORD LowPart;
    LONG  HighPart;
  } u;
  LONGLONG QuadPart;
} LARGE_INTEGER;

typedef LARGE_INTEGER *PLARGE_INTEGER;

typedef union _ULARGE_INTEGER {
  struct {
    DWORD LowPart;
    DWORD HighPart;
  } DUMMYSTRUCTNAME;
  struct {
    DWORD LowPart;
    DWORD HighPart;
  } u;
  ULONGLONG QuadPart;
} ULARGE_INTEGER;

typedef ULARGE_INTEGER *PULARGE_INTEGER;