文字列関数
strcat
_mbscat
wcscat
Ascii
Unicode
ShiftJis
strcpy
_mbscpy
wcscpy
補足
wcslen は文字数(≠バイト数)
_mbstrlen は、マルチバイト文字の正当性を見る
_mbslen
_mbstrlen
wcslen
strlen
wcsncmp
strncmp
文字列型
LPCTSTR
windows.h
const wchar_t*
型名
意味
ヘッダ
wchar_t
ワイド文字型
tchar.h
補足
VS2005 では組み込み型、
unsigned short と同じではない
_TCHAR
char/wchar_t 兼用
tchar.h
(wcs)
(mbs)
_tcscpy
_tcscat
_tcslen
sprintf
wsprintf
strchr
wcschr
_mbschr
_tcschr
strstr
wcsstr
_mbsstr
_tcsstr
_stprintf
_vsnwprintf
#ifdef __cplusplus
#define _M(x) reinterpret_cast<unsigned char*> ## (x)
#else
#define _M(x) ( (unsigned char*)(x) )
#endif
_mbscpy_s( ss, sizeof(ss), _M("あabcde") );
マルチバイト文字列です。 1文字あたりのサイズは可変です。日本なら Shift-JIS です。
型は、unsigned char* です。
ただし、リテラル文字列が char* なので、下記のように型変換する必要があります。
#ifdef _UNICODE
#error Unicode version
#else
#ifdef _MBCS
#error MBCS (Multi byte character set) version
#else
#error SBCS (Single byte character set) version
#endif
#endif
_TCHAR の文字型を切り替えるには、コンパイルオプションで、_UNICODE または _MBCS を定義
します。 コンパイル時の文字型を調べるには、以下のコードを使います。
char 型と wchar_t 型のどちらにもコンパイルできるようにした文字の型です。
VisualC++ 6.0、PB5 までは、先頭にアンダーラインが付きません。(TCHAR)
_tprintf( _T("ERROR in %s, %d"), _T(__FILE__), __LINE__ );
%s は、_TCHAR の設定に従う。
%S は、設定と逆をとる。
TEXT("リテラル文字列")
関数名の末尾に _l (アンダースコア+小文字のエル) が付いているものは、
ロケール(地域)を指定する引数を持っています。
_l が付いていない関数は、デフォルト、または setlocale 関数で指定したロケールとして処理します。
セキュアな関数は、メモリ領域を超えて Write しそうになったとき、それ以上 Write しないで、
領域の最後に '\0' 文字を入れて、
エラーになります。
_TRUNCATE を指定すると、エラーになりません。
デバッグ版のほとんどの関数では、関数に指定した領域の全体を、一度 0xDF で Write します。
この動作により、領域のサイズを誤って大きく指定した場合に、別の変数の値がおかしくなったり、
不正な Write 命令の例外が発生する可能性が高まり、早期デバッグの役に立ちます。
リリース版では、無駄な処理となるため、デバッグ版で DF と書かれたメモリにアクセスしません。
char s[4];
strcpy_s( s, 8, "abc" );
CC CC CC CC
61 62 63 00
DF DF DF DF
char sp[4];
strcpy_s( sp, sizeof(sp), "abcdefg" );
領域を超えてアクセスしようとすると、アプリケーションは PC が乗っ取られる前にすぐに
異常終了します。
← ここで異常終了
expression = (L"Buffer is too small" && 0)
function = strcpy_s
file = .\tcscpy_s.inl
line = 30
void my_err( const wchar_t * expression, const wchar_t * function,
const wchar_t * file, unsigned int line, uintptr_t pReserved );
_invalid_parameter_handler err;
err = _set_invalid_parameter_handler( my_err );
エラーハンドラにわたってくる変数の値の例:
エラーハンドラから戻ると、元のプログラムに復帰します。
異常終了したいときは、エラーハンドラの中で、exit や TerminateProcess してください。
_s 関数
_set_invalid_parameter_handler
my_err エラーハンドラ
異常時
あらかじめエラーハンドラを登録しておく
復帰 return
exit など
異常終了
アプリ
_set_invalid_parameter_handler でエラーハンドラが登録してある状態で、_s 関数で異常が発生した
ときは、まずエラーハンドラを呼び出します。
正常時
_set_invalid_parameter_handler でエラーハンドラが登録してない状態で、_s 関数で異常が発生した
ときは、Assertion が発生して原因をプログラマに知らせます。
しかし、デバッグ版(その続きを実行して)もリリース版も、そこでプログラムが異常終了します。
atexit で登録した関数は呼ばれません。
TerminateProcess
正常時
アプリ
_s 関数
異常時
バッファ・オーバーフローしたときの動き
char s[8];
int r;
r = sprintf_s( s, sizeof(s), "%s", "123456789" );
下記のコードでは、バッファ・オーバーフローが発生します。
バッファ・オーバーフローが発生すると、Assertion に失敗します。
Debug Assertion Failed!
Buffer too small
続けて実行すると、異常終了します。
errno_t strncpy_s( char* dst, size_t dst_n, char* src, size_t n );
wcsncpy_s
_mbsncpy_s_l
_wcsncpy_s_l
_strncpy_s_l
_mbsncpy_s
strncpy_s
Unicode
Shift-JIS
Ascii
通常版
文字列を n 文字だけコピーします。
strncpy_s( s, sizeof(s), "abcde", 2 );
_mbsncpy_s( ss, sizeof(ss), _M("あabcde"), 2 );
wcsncpy_s( sss, sizeof(sss)/2, L"あabcde", 2 );
s 61 62 00 FD FD FD FD FD
ss 82 A0 61 00 FD FD FD FD
sss 42 30 61 00 00 00 FD FD
を指定したら、文字列すべてをコピーしようとして、エラーは発生しません。
n に
strncpy のように、'\0' 文字の
後も '\0' で埋めることはしません。
vs2005 サンプル → test.lzh
_stprintf_s
_snprintf
int _snprintf( char* buffer, size_t count, const char *format [, ... ] );
buffer のあふれをチェックする sprintf です。
セキュア版 _snprintf_s もあります。
vc6
int _vsnprintf( char* buffer, size_t count, const char* format, va_list argptr );
vc6
buffer のあふれをチェックする sprintf です。 va_list をとります。
int _vsntprintf( LPTSTR buffer, size_t n_tchar, LPCTSTR format, va_list argptr );
n_tchar は、文字数(≠バイト数)です。