世界上的书面语言文字根本无法用256个8位代码来表示。而DBCS的解决方法是不足且笨拙的。因此可以使用16位代码的Unicode。
Unicode被认为是“宽字符”。每一个Unicode中的字符是16位宽,8位值在Unicode中是无意义的。
-------------------------------------宽字符函数------------------------------------------
使用Unicode不会改变C语言中的字符数据类型。char仍表示1个字节的存储空间。
C语言中的宽字符是基于wchar_t数据类型的,其被定义在多个头文件中,包括WCHAR.H
: typedef unsigned short wchar_t
因此wchar_t是16位宽。可以定义一个已初始化的指向宽字符串的指针
: wchar_t *p = L"Hello!";
“L”表示这个字符串用宽字符存储,每个字符占用2个字节。因此这个字符串需要16个字节存储空间
- wcslen为宽字符字符串长度函数,定义在SYRING.H和WCHAR.H中
- size_t __cdec1 wcslen (const wchar_t*)
使用宽字符时,字符串的字符长度并没有改变,改变的是字节长度
-----------------------------------维护源代码文件---------------------------------------
使用包含在Microsoft Visual C++中的TCHAR.H头文件。其为需要字符串参数的普通运行库函数提供了一系列替代名称。这些替代名称有时被称为通用名称,因为可以指Unicode和非Unicode的函数。
如果一个命名为_UNICODE的标识符被定义了,并且TCHAR.H头文件被包含在程序中,_tcslen就被定义为wcslen: #define _tcslen wcslen
如果未定义: #define _tcslen strlen - 如果_UNICODE被定义,__T的宏是如下定义的
- #define __T(x) L##x
其中的数字符号被称为“令牌粘贴”,使得字母L与宏参数拼接在一起。如果宏参数是“Hello!”,L##x == L"Hello!"
如果未定义,__T宏就如下定义 - #define __T(x) x
-----------------------------------Windows函数调用------------------------------------
MessageBox函数
存在于动态链接库USER.EXE中,其定义如下 - int WINAPI MessageBox (HWND, LPCSTR, LPCSTR, UNIT);
第2与第3个参数是指向常量字符串的指针。当Windows编译和链接一个Win16程序时,并不处理MessageBox调用。而是执行程序.EXE文件中的一张表格,允许Windows将该程序的调用与动态链接库USER中的MessageBox函数动态链接起来。
32位Windows除了含有USER.EXE外,还含有一个称为USER32.DLL的动态链接库,该动态链接库含有32位用户界面函数的入口点,其中包含了32位版本的函数MessageBox
但USER32.DLL中不含有32位MessageBox的入口点,实际上,其拥有两个入口点
- MessageBoxA
WINUSERAPI int WINAPI MessageBoxA (HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UNIT uType); - MessageBoxW
WINUSERAPI int WINAPI MessageBoxW (HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UNIT uType);
区别在于第2和第3个参数,BoxW是2个指向宽字符的指针
-----------------------------------在Windows中起作用的printf--------------------------
下面是 <stdarg.h> 里面重要的几个宏定义如下:
typedef char* va_list;
void va_start ( va_list ap, prev_param ); /* ANSI version */
type va_arg ( va_list ap, type );
void va_end ( va_list ap );
va_list 是一个字符指针,可以理解为指向当前参数的一个指针,取参必须通过这个指针进行。
<Step 1> 在调用参数表之前,定义一个 va_list 类型的变量,(假设va_list 类型变量被定义为ap);
<Step 2> 然后应该对ap 进行初始化,让它指向可变参数表里面的第一个参数,这是通过 va_start 来实现的,第一个参数是 ap 本身,第二个参数是在变参表前面紧挨着的一个变量,即“…”之前的那个参数;
<Step 3> 然后是获取参数,调用va_arg,它的第一个参数是ap,第二个参数是要获取的参数的指定类型,然后返回这个指定类型的值,并且把 ap 的位置指向变参表的下一个变量位置; <Step 4> 获取所有的参数之后,我们有必要将这个 ap 指针关掉,以免发生危险,方法是调用 va_end,他是输入的参数 ap 置为 NULL,应该养成获取完参数表之后关闭指针的习惯。说白了,就是让我们的程序具有健壮性。通常va_start和va_end是成对出现。
int sprintf (char * szBuffer, const char * szFormat, …)
{
int iReturn;
val_list pArgs;
va_start (pArgs, szFormat);
iReturn = vsprintf (szBuffer, szFormat, pArgs);
va_end (pArgs);
return iReturn;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。