seraphyの日記

日記というよりは過去を振り返るときのための単なる備忘録

_tfindfirst64のなぞ

VisualC++でソースを書くとき、マルチバイト版とUNICDE版とで共通にかけるようにTCHAR系のAPIを用いる。これはマクロでコンパイル時にマルチバイト版かUNICODE版の、どちらかに翻訳される。
同様にCランタイムでも同じようにTCHAR系がサポートされている。

このfindfirst64関数のTCHAR版である、_tfindfirst64をUNICODEでビルドすると、第1引数に「const wchar_t *」ではなく「wchar_t *」を渡すように要求される。
不可解なのでヘッダを検索すると、
Microsoft Visual Studio .NET 2003\Vc7\include\wchar.h
で宣言されている_wfindfirst64が、


#if _INTEGRAL_MAX_BITS >= 64
_CRTIMP intptr_t __cdecl _wfindfirsti64(wchar_t *, struct _wfinddatai64_t *);
_CRTIMP intptr_t __cdecl _wfindfirst64(wchar_t *, struct __wfinddata64_t *);
_CRTIMP int __cdecl _wfindnexti64(intptr_t, struct _wfinddatai64_t *);
_CRTIMP int __cdecl _wfindnext64(intptr_t, struct __wfinddata64_t *);
#endif

のようになっている。

そして、Microsoft Visual Studio .NET 2003\Vc7\include\io.hで宣言されているものは、


#if _INTEGRAL_MAX_BITS >= 64
_CRTIMP intptr_t __cdecl _wfindfirsti64(const wchar_t *, struct _wfinddatai64_t *);
_CRTIMP int __cdecl _wfindnexti64(intptr_t, struct _wfinddatai64_t *);
_CRTIMP intptr_t __cdecl _wfindfirst64(const wchar_t *, struct __wfinddata64_t *);
_CRTIMP int __cdecl _wfindnext64(intptr_t, struct __wfinddata64_t *);
#endif

である。

tchar.hが呼び出されたときにUNICDEであればwchar.hが呼び出され、そのとき、まだio.hが呼び出されていないならば、wchar.hでwfindnexti64の宣言がおこなわれる。

したがって、tchar.hよりも先にio.hを呼び出しておけば、「const wchar_t *」の引数となる。

おそらく、これはVisualStudioのランタイム関数のバグだと思われるが、あるいは、なにか特別の意図があり、あえてconstを外すケースを想定しているのかもしれない。