32ビットWindows環境で、新しいデータ型の使用はプログラムの安全性(堅牢性)を図れるのか?

|

昨年末からの煽られたコロナ禍で、再度の非常事態宣言。暇が有り過ぎて、64ビット化擬きの真似事をしてみる事に。

だけど、ハードやOSはとっくに64ビット化して10年以上経つのに、64ビットアプリケーションってMSオフィス以外殆ど存在しない状況? だったりして。

なんたって仮想マシンWOW64(Windows 32 On Windows 64)の出来が良過ぎたのか? それとも一般には未だに32ビットアプリで十分なのか? いやいや特殊職以外64ビットアプリなんて抑々不必要?

そんなこんなで、ウィキペディアで64ビットの項目を読んでみると、何とも驚いた事に!

C言語およびC++では、char型を除く組み込みの整数型(short型やint型、long型)は、最低限のビット数や大小関係しか規定していない。C99規格およびC++11規格では、int32_t や int64_t などビット数を規定した固定幅整数型(stdint.h および cstdint にて定義される)を追加し、また64ビット以上の値を表現できることが保証されるlong long型を追加した。

まったくぅ、だからC++は愛想を尽かされるんだよ。基本データ型のサイズ位さっさと規定しろよ! って言いたくなりますよね?

更には、プログラマはしばしば、ポインタとint或いはlongが同じ大きさであるという前提でコードを書いてきた問題があります、と。
つまり、多くのコードが32ビット環境を前提として書かれてきたため、64ビット環境ではこの仮定が度々問題を引き起こす可能性が有りますよ。

そんな訳で先ずは、32ビットWindows環境のデータサイズを確認しようとしたところ、以前の「Windowsプログラムのいろはは、DOS窓でWin32API」で書いたように、素人には64ビット化は任せられないとマイクロソフトが想定したかどうかは分かりませんが、Windows環境に「固定精度整数型」「ポインター精度整数型」「固定精度ポインター型」という3つの新しいデータ型を追加していました。

これらのデータ型を使用すると、64ビット化の準備を整えることが出来るそうです。試しに、これらを含めたデータサイズをチェックするだけのサンプルを作ってみました。


<注意点>

・固定精度整数型は、32ビット用と64ビット用のプログラムで同じ長さ(サイズ)に成ります。

・ポインター精度整数型は、32ビット用にコンパイルされれば32ビット長に、64ビット用にコンパイルされれば64ビット長になります。

・固定精度ポインター型は、長さを32ビットまたは64ビットに明示的に指定します。

・ボイド型ポインタ(void *、別名汎用ポインタ)の参照先変数への読み書きは出来ません。⇒「error C2100: 間接指定演算子 (*) の使い方が正しくありません。」

・POINTER_32、POINTER_64 の型に long long や double なども指定可能だと思いますが、確かめていません。

・マイクロソフトのドキュメントには、新しいデータ型を採用する事で、コードの堅牢性が向上します。(コードを)安全にするには、新しいデータ型を使用します。とあります。

・ドキュメントでは、HWND、HINSTANCE、HDC の3つもボイド型ポインタだろうと思うのですが、コンパイルエラーはそうではないと言っているような(永遠にお手上げ?)。


【32ビットWindows環境のデータ型一覧】

基本型
タイプ定義データ幅ポインタ幅
char 1バイト 4バイト
short 2バイト 4バイト
int 4バイト 4バイト
long 4バイト 4バイト

 「long long」型は不使用が良いかと

固定精度整数型
タイプ定義データ幅ポインタ幅
DWORD32 32ビット符号無し整数 4バイト 4バイト
DWORD64 64ビット符号無し整数 8バイト 4バイト
INT32 32ビット符号付き整数 4バイト 4バイト
UINT32 32ビット符号無し整数 4バイト 4バイト
INT64 64ビット符号付き整数 8バイト 4バイト
UINT64 64ビット符号無し整数 8バイト 4バイト
LONG32 32ビット符号付き整数 4バイト 4バイト
ULONG32 32ビット符号無し整数 4バイト 4バイト
LONG64 64ビット符号付き整数 8バイト 4バイト
ULONG64 64ビット符号無し整数 8バイト 4バイト

 

ポインタ精度整数型
タイプ定義データ幅ポインタ幅
DWORD_PTR ポインタ有効ビット数の符号無し整数 4バイト 4バイト
INT_PTR ポインタ有効ビット数の符号付き整数 4バイト 4バイト
UINT_PTR ポインタ有効ビット数の符号無し整数 4バイト 4バイト
LONG_PTR ポインタ有効ビット数の符号付き整数 4バイト 4バイト
ULONG_PTR ポインタ有効ビット数の符号無し整数 4バイト 4バイト
SIZE_T ポインタが参照できる符号無し最大バイト数 *1 4バイト 4バイト
SSIZE_T ポインタが参照できる符号付き最大バイト数 *1 4バイト 4バイト
HALF_PTR ポインタ有効ビット数半分の符号付き整数 *2 2バイト 4バイト
UHALF_PTR ポインタ有効ビット数半分の符号無し整数 *2 2バイト 4バイト

 *1:ポインタの範囲全体にまたがる必要があるカウントに使用。
 *2:32ビットシステムでは16ビット、64ビットシステムでは32ビット。

文字列型
タイプ定義データ幅ポインタ幅
PSTR 1バイト文字列のポインタ 1バイト 4バイト
LPSTR 1バイト文字列のポインタ 1バイト 4バイト
PCSTR 1バイト文字列のポインタ 1バイト 4バイト
LPCSTR 1バイト文字列のポインタ 1バイト 4バイト
PWSTR 2バイト文字列のポインタ *1 2バイト 4バイト
LPWSTR 2バイト文字列のポインタ *1 2バイト 4バイト
PCWSTR 2バイト文字列のポインタ *1 2バイト 4バイト
LPCWSTR 2バイト文字列のポインタ *1 2バイト 4バイト
PTSTR 1バイト文字列のポインタ 1バイト 4バイト
LPTSTR 1バイト文字列のポインタ 1バイト 4バイト
PCTSTR 1バイト文字列のポインタ 1バイト 4バイト
LPCTSTR 1バイト文字列のポインタ 1バイト 4バイト

 *1:UNICODE文字列に対応。

ウインドウ型
タイプ定義データ幅ポインタ幅
LPARAM ポインタ有効ビット数の符号付き整数 4バイト 4バイト
WPARAM ポインタ有効ビット数の符号付き整数 4バイト 4バイト
LRESULT ポインタ有効ビット数の符号付き整数 4バイト 4バイト
LPVOID ボイドのポインタ 無効 *1 4バイト
HANDLE ボイドのポインタ 無効 *1 4バイト
HWND ‐?‐ *2 無効? 4バイト
HINSTANCE ‐?‐ *2 無効? 4バイト
HDC ‐?‐ *2 無効? 4バイト

 *1:アクセス不可を示す。
 *2:'HWND__' 'HINSTANCE__' 'HDC__' は、今のところ(永久に?)不明、アクセス不可?

固定精度ポインタ型
タイプ定義データ幅ポインタ幅
POINTER_32 32ビットポインタ *1 指定サイズ依存 4バイト
POINTER_64 64ビットポインタ *2 *3 指定サイズ依存 8バイト

 *1:32ビットシステムではネイティブポインタ、64ビットシステムでは切り捨てられた64ビットポインタ。
 *2:64ビットシステムではネイティブポインタ、32ビットシステムでは符号拡張32ビットポインタ。
 *3:32ビットシステムでは上位ポインタのビット状態を想定するのは安全ではありません。


お試し環境
  WindowsXP 32bit Edition
  Visual C++ 2008


/*---- 32ビットデータ型確認 ---------------- コマンドライン --------------*/

D:\vc2008\x86x64>cl test.c

/*----------------------------------------------------------------------------*/


/*-------------------------------- お試し結果 ------------------------------*/

D:\vc2008\x86x64>test
基本型
sizeof(a) = 1, sizeof(char *) = 4, a = 0x12
sizeof(b) = 2, sizeof(short *) = 4, b = 0x1234
sizeof(c) = 4, sizeof(int *) = 4, c = 0x12345678
sizeof(d) = 4, sizeof(long *) = 4, d = 0x12345678

固定精度整数型
sizeof(f) = 4, sizeof(DWORD32 *) = 4, f = 0x12345678
sizeof(g) = 8, sizeof(DWORD64 *) = 4, g = 0x1234567890abcdef
sizeof(h) = 4, sizeof(INT32 *) = 4, h = 0x12345678
sizeof(i) = 4, sizeof(UINT32 *) = 4, i = 0x12345678
sizeof(j) = 8, sizeof(INT64 *) = 4, j = 0x1234567890abcd12
sizeof(k) = 8, sizeof(UINT64 *) = 4, k = 0x1234567812345678
sizeof(l) = 4, sizeof(LONG32 *) = 4, l = 0x12345678
sizeof(m) = 4, sizeof(ULONG32 *) = 4, m = 0x12345678
sizeof(n) = 8, sizeof(LONG64 *) = 4, n = 0x1234567890ab1234
sizeof(o) = 8, sizeof(ULONG64 *) = 4, o = 0x1234567812345678

ポインタ精度整数型
sizeof(p) = 4, sizeof(DWORD_PTR *) = 4, p = 0x12345678
sizeof(q) = 4, sizeof(INT_PTR *) = 4, q = 0x12345678
sizeof(r) = 4, sizeof(UINT_PTR *) = 4, r = 0x12345678
sizeof(s) = 4, sizeof(LONG_PTR *) = 4, s = 0x12345678
sizeof(t) = 4, sizeof(ULONG_PTR *) = 4, t = 0x12345678
sizeof(u) = 4, sizeof(SIZE_T *) = 4, u = 0x12345678
sizeof(v) = 4, sizeof(SSIZE_T *) = 4, v = 0x12345678
sizeof(w) = 2, sizeof(HALF_PTR *) = 4, w = 0x1234
sizeof(x) = 2, sizeof(UHALF_PTR *) = 4, x = 0x1234

文字列型
sizeof(*sa) = 1, sizeof(PSTR) = 4, *sa = 1
sizeof(*sb) = 1, sizeof(LPSTR) = 4, *sb = 2
sizeof(*sc) = 1, sizeof(PCSTR) = 4, *sc = A
sizeof(*sd) = 1, sizeof(LPCSTR) = 4, *sd = A
sizeof(*se) = 2, sizeof(PWSTR) = 4, *se = 3
sizeof(*sf) = 2, sizeof(LPWSTR) = 4, *sf = 4
sizeof(*sg) = 2, sizeof(PCWSTR) = 4, *sg = A
sizeof(*sh) = 2, sizeof(LPCWSTR) = 4, *sh = A
sizeof(*si) = 1, sizeof(PTSTR) = 4, *si = 5
sizeof(*sj) = 1, sizeof(LPTSTR) = 4, *sj = 6
sizeof(*sk) = 1, sizeof(PCTSTR) = 4, *sk = A
sizeof(*sl) = 1, sizeof(LPCTSTR) = 4, *sl = A

ウインドウ型
sizeof(wa) = 4, sizeof(LPARAM *) = 4, wa = 0x12345678
sizeof(wb) = 4, sizeof(WPARAM *) = 4, wb = 0x12345678
sizeof(wc) = 4, sizeof(LRESULT *) = 4, wc = 0x12345678
sizeof(wd) = 4, sizeof(LPVOID *) = 4
sizeof(we) = 4, sizeof(HANDLE *) = 4
sizeof(wf) = 4, sizeof(HWND *) = 4
sizeof(wg) = 4, sizeof(HINSTANCE *) = 4
sizeof(wh) = 4, sizeof(HDC *) = 4

固定精度ポインタ型
sizeof(ya) = 4, sizeof(char *) = 4, *ya = 0x12
sizeof(yb) = 4, sizeof(int *) = 4, *yb = 0x12345678
sizeof(yc) = 4, sizeof(void *) = 4
sizeof(za) = 8, sizeof(short *) = 4, *za = 0x1234
sizeof(zb) = 8, sizeof(long *) = 4, *zb = 0x12345678
sizeof(zc) = 8, sizeof(void *) = 4

/*----------------------------------------------------------------------------*/


/*---- test.c ------------------------ お試しソース ------------------------*/

#include <stdio.h>
#include <windows.h>

int main(int argc, char *argv[])
{
// 基本型
    char a = 0x12;
    short b = 0x1234;
    int c = 0x12345678;
    long d = 0x12345678;

// 固定精度整数型
    DWORD32 f = 0x12345678;
    DWORD64 g = 0x1234567890abcdef;
    INT32 h = 0x12345678;
    UINT32 i = 0x12345678;
    INT64 j = 0x1234567890abcdef;
    UINT64 k = 0x1234567890abcdef;
    LONG32 l = 0x12345678;
    ULONG32 m = 0x12345678;
    LONG64 n = 0x1234567890abcdef;
    ULONG64 o = 0x1234567890abcdef;

// ポインタ精度整数型
    DWORD_PTR p = 0x12345678;
    INT_PTR q = 0x12345678;
    UINT_PTR r = 0x12345678;
    LONG_PTR s = 0x12345678;
    ULONG_PTR t = 0x12345678;
    SIZE_T u = 0x12345678;
    SSIZE_T v = 0x12345678;
    HALF_PTR w = 0x1234;
    UHALF_PTR x = 0x1234;

// 文字列型
    PSTR sa = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    LPSTR sb = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    PCSTR sc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    LPCSTR sd = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    PWSTR se = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    LPWSTR sf = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    PCWSTR sg = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    LPCWSTR sh = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    PTSTR si = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    LPTSTR sj = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    PCTSTR sk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    LPCTSTR sl = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

// ウインドウ型
    LPARAM wa = 0x12345678;
    WPARAM wb = 0x12345678;
    LRESULT wc = 0x12345678;
    LPVOID wd = (LPVOID)0x12345678;
    HANDLE we = (HANDLE)0x12345678;
    HWND wf = (HWND)0x12345678;
    HINSTANCE wg = (HINSTANCE)0x12345678;
    HDC wh = (HDC)0x12345678;

// 固定精度ポインタ型
    char *POINTER_32 ya = (char *)0x12345678;
    int *POINTER_32 yb = (int *)0x12345678;
    void *POINTER_32 yc = (void *)0x12345678;
    short *POINTER_64 za = (short *)0x12345678; // warning C4826: 'short *' から 'short *' への変換は符号拡張されています。これは、予期しない実行時の動作を発生させる可能性があります。
    long *POINTER_64 zb = (long *)0x12345678; // warning C4826: 'long *' から 'long *' への変換は符号拡張されています。これは、予期しない実行時の動作を発生させる可能性があります。
    void *POINTER_64 zc = (void *)0x12345678; // warning C4826: 'void *' から 'void *' への変換は符号拡張されています。これは、予期しない実行時の動作を発生させる可能性があります。


// ウインドウ型チェック
    wd = &p;
    we = &q;
    wf = (HWND)&r;
    wg = (HINSTANCE)&s;
    wh = (HDC)&t;

//  *wd = 0x11; error C2100: 間接指定演算子 (*) の使い方が正しくありません。
//  *we = 0x22; error C2100: 間接指定演算子 (*) の使い方が正しくありません。
//  *wf = 0x33; error C2440: '=' : 'int' から 'HWND__' に変換できません。
//  *wg = 0x44; error C2440: '=' : 'int' から 'HINSTANCE__' に変換できません。
//  *wh = 0x55; error C2440: '=' : 'int' から 'HDC__' に変換できません。

// 固定精度ポインタ型チェック
    ya = (char *)&j;
    yb = (int *)&k;
    yc = &g;
    za = (short *)&n; // warning C4826: 'short *' から 'short *' への変換は符号拡張されています。これは、予期しない実行時の動作を発生させる可能性があります。
    zb = (long *)&o; // warning C4826: 'long *' から 'long *' への変換は符号拡張されています。これは、予期しない実行時の動作を発生させる可能性があります。
    zc = &g; // warning C4826: 'DWORD64 *' から 'void *' への変換は符号拡張されています。これは、予期しない実行時の動作を発生させる可能性があります。

    *ya = 0x12;
    *yb = 0x12345678;
//  *yc = 0x1234567890abcdef; error C2100: 間接指定演算子 (*) の使い方が正しくありません。
    *za = 0x1234;
    *zb = 0x12345678;
//  *zc = 0x1234567890abcdef; error C2100: 間接指定演算子 (*) の使い方が正しくありません。

// 文字列型チェック
    *sa = '1';
    *sb = '2';
//  *sc = '3'; error C2166: 左辺値は const オブジェクトに指定されています。
//  *sd = '4'; error C2166: 左辺値は const オブジェクトに指定されています。
    *se = '3';
    *sf = '4';
//  *sg = '7'; error C2166: 左辺値は const オブジェクトに指定されています。
//  *sh = '8'; error C2166: 左辺値は const オブジェクトに指定されています。
    *si = '5';
    *sj = '6';
//  *sk = '1'; error C2166: 左辺値は const オブジェクトに指定されています。
//  *sl = '2'; error C2166: 左辺値は const オブジェクトに指定されています。


// 基本型データ出力
    printf("基本型\n");
    printf("sizeof(a) = %d, sizeof(char *) = %d, a = %#x\n", sizeof(a), sizeof(char *), a);
    printf("sizeof(b) = %d, sizeof(short *) = %d, b = %#x\n", sizeof(b), sizeof(short *), b);
    printf("sizeof(c) = %d, sizeof(int *) = %d, c = %#x\n", sizeof(c), sizeof(int *), c);
    printf("sizeof(d) = %d, sizeof(long *) = %d, d = %#x\n", sizeof(d), sizeof(long *), d);

// 固定精度整数型データ出力
    printf("\n固定精度整数型\n");
    printf("sizeof(f) = %d, sizeof(DWORD32 *) = %d, f = %#x\n", sizeof(f), sizeof(DWORD32 *), f);
    printf("sizeof(g) = %d, sizeof(DWORD64 *) = %d, g = %#llx\n", sizeof(g), sizeof(DWORD64 *), g);
    printf("sizeof(h) = %d, sizeof(INT32 *) = %d, h = %#x\n", sizeof(h), sizeof(INT32 *), h);
    printf("sizeof(i) = %d, sizeof(UINT32 *) = %d, i = %#x\n", sizeof(i), sizeof(UINT32 *), i);
    printf("sizeof(j) = %d, sizeof(INT64 *) = %d, j = %#llx\n", sizeof(j), sizeof(INT64 *), j);
    printf("sizeof(k) = %d, sizeof(UINT64 *) = %d, k = %#llx\n", sizeof(k), sizeof(UINT64 *), k);
    printf("sizeof(l) = %d, sizeof(LONG32 *) = %d, l = %#x\n", sizeof(l), sizeof(LONG32 *), l);
    printf("sizeof(m) = %d, sizeof(ULONG32 *) = %d, m = %#x\n", sizeof(m), sizeof(ULONG32 *), m);
    printf("sizeof(n) = %d, sizeof(LONG64 *) = %d, n = %#llx\n", sizeof(n), sizeof(LONG64 *), n);
    printf("sizeof(o) = %d, sizeof(ULONG64 *) = %d, o = %#llx\n", sizeof(o), sizeof(ULONG64 *), o);

// ポインタ精度整数型データ出力
    printf("\nポインタ精度整数型\n");
    printf("sizeof(p) = %d, sizeof(DWORD_PTR *) = %d, p = %#x\n", sizeof(p), sizeof(DWORD_PTR *), p);
    printf("sizeof(q) = %d, sizeof(INT_PTR *) = %d, q = %#x\n", sizeof(q), sizeof(INT_PTR *), q);
    printf("sizeof(r) = %d, sizeof(UINT_PTR *) = %d, r = %#x\n", sizeof(r), sizeof(UINT_PTR *), r);
    printf("sizeof(s) = %d, sizeof(LONG_PTR *) = %d, s = %#x\n", sizeof(s), sizeof(LONG_PTR *), s);
    printf("sizeof(t) = %d, sizeof(ULONG_PTR *) = %d, t = %#x\n", sizeof(t), sizeof(ULONG_PTR *), t);
    printf("sizeof(u) = %d, sizeof(SIZE_T *) = %d, u = %#x\n", sizeof(u), sizeof(SIZE_T *), u);
    printf("sizeof(v) = %d, sizeof(SSIZE_T *) = %d, v = %#x\n", sizeof(v), sizeof(SSIZE_T *), v);
    printf("sizeof(w) = %d, sizeof(HALF_PTR *) = %d, w = %#x\n", sizeof(w), sizeof(HALF_PTR *), w);
    printf("sizeof(x) = %d, sizeof(UHALF_PTR *) = %d, x = %#x\n", sizeof(x), sizeof(UHALF_PTR *), x);

// 文字列型データ出力
    printf("\n文字列型\n");
    printf("sizeof(*sa) = %d, sizeof(PSTR) = %d, *sa = %c\n", sizeof(*sa), sizeof(PSTR), *sa);
    printf("sizeof(*sb) = %d, sizeof(LPSTR) = %d, *sb = %c\n", sizeof(*sb), sizeof(LPSTR), *sb);
    printf("sizeof(*sc) = %d, sizeof(PCSTR) = %d, *sc = %c\n", sizeof(*sc), sizeof(PCSTR), *sc);
    printf("sizeof(*sd) = %d, sizeof(LPCSTR) = %d, *sd = %c\n", sizeof(*sd), sizeof(LPCSTR), *sd);
    printf("sizeof(*se) = %d, sizeof(PWSTR) = %d, *se = %c\n", sizeof(*se), sizeof(PWSTR), *se);
    printf("sizeof(*sf) = %d, sizeof(LPWSTR) = %d, *sf = %c\n", sizeof(*sf), sizeof(LPWSTR), *sf);
    printf("sizeof(*sg) = %d, sizeof(PCWSTR) = %d, *sg = %c\n", sizeof(*sg), sizeof(PCWSTR), *sg);
    printf("sizeof(*sh) = %d, sizeof(LPCWSTR) = %d, *sh = %c\n", sizeof(*sh), sizeof(LPCWSTR), *sh);
    printf("sizeof(*si) = %d, sizeof(PTSTR) = %d, *si = %c\n", sizeof(*si), sizeof(PTSTR), *si);
    printf("sizeof(*sj) = %d, sizeof(LPTSTR) = %d, *sj = %c\n", sizeof(*sj), sizeof(LPTSTR), *sj);
    printf("sizeof(*sk) = %d, sizeof(PCTSTR) = %d, *sk = %c\n", sizeof(*sk), sizeof(PCTSTR), *sk);
    printf("sizeof(*sl) = %d, sizeof(LPCTSTR) = %d, *sl = %c\n", sizeof(*sl), sizeof(LPCTSTR), *sl);

// ウインドウ型データ出力
    printf("\nウインドウ型\n");
    printf("sizeof(wa) = %d, sizeof(LPARAM *) = %d, wa = %#x\n", sizeof(wa), sizeof(LPARAM *), wa);
    printf("sizeof(wb) = %d, sizeof(WPARAM *) = %d, wb = %#x\n", sizeof(wb), sizeof(WPARAM *), wb);
    printf("sizeof(wc) = %d, sizeof(LRESULT *) = %d, wc = %#x\n", sizeof(wc), sizeof(LRESULT *), wc);
    printf("sizeof(wd) = %d, sizeof(LPVOID *) = %d\n", sizeof(wd), sizeof(LPVOID *));
    printf("sizeof(we) = %d, sizeof(HANDLE *) = %d\n", sizeof(we), sizeof(HANDLE *));
    printf("sizeof(wf) = %d, sizeof(HWND *) = %d\n", sizeof(wf), sizeof(HWND *));
    printf("sizeof(wg) = %d, sizeof(HINSTANCE *) = %d\n", sizeof(wg), sizeof(HINSTANCE *));
    printf("sizeof(wh) = %d, sizeof(HDC *) = %d\n", sizeof(wh), sizeof(HDC *));

// 固定精度ポインタ型データ出力
    printf("\n固定精度ポインタ型\n");
    printf("sizeof(ya) = %d, sizeof(char *) = %d, *ya = %#x\n", sizeof(ya), sizeof(char *), *ya);
    printf("sizeof(yb) = %d, sizeof(int *) = %d, *yb = %#x\n", sizeof(yb), sizeof(int *), *yb);
//  printf("sizeof(yc) = %d, sizeof(void *) = %d, *yc = %d\n", sizeof(yc), sizeof(void *), *yc); error C2100: 間接指定演算子 (*) の使い方が正しくありません。
    printf("sizeof(yc) = %d, sizeof(void *) = %d\n", sizeof(yc), sizeof(void *));
    printf("sizeof(za) = %d, sizeof(short *) = %d, *za = %#x\n", sizeof(za), sizeof(short *), *za);
    printf("sizeof(zb) = %d, sizeof(long *) = %d, *zb = %#x\n", sizeof(zb), sizeof(long *), *zb);
//  printf("sizeof(zc) = %d, sizeof(void *) = %d, *zc = %d\n", sizeof(zc), sizeof(void *), *zc); error C2100: 間接指定演算子 (*) の使い方が正しくありません。
    printf("sizeof(zc) = %d, sizeof(void *) = %d\n", sizeof(zc), sizeof(void *));

    return(0);
}

/*----------------------------------------------------------------------------*/
/*============================================================================*/