C标准库源码解剖(3):字符处理函数ctype.h和wctype.h

    字符处理包括分类(即属性判断)和转换函数。ASCII字符主要可分类为控制字符、空白字符、可打印字符、数字字符、字母字符(大写和小写)、标点符号等。
    1、ctype.h: 标准的属性判断函数有isalnum,isalpha,iscntrl,isdigit,isxdigit,isgraph,isprint,ispunct,islower,isupper,isspace, isblank(C99中引入)共12个函数。标准的属性转换函数有tolower和toupper。当然具体的实现中还会提供一些非标准函数作为扩展,如glibc的实现中提供了isctype,isascii,toascii。

/* ISO C99 Standard 7.4: 字符处理	<ctype.h> */
#ifndef	_CTYPE_H
#define	_CTYPE_H	1
#include <features.h>   /* 定义了一些表示编译选项的宏 */
#include <bits/types.h>
__BEGIN_DECLS
#ifndef _ISbit
/* 下面这些是所有的字符属性,如果超过16种不同的属性,那很多使用unsigned short int的
    的函数代码都要改变。这些属性被存储为网络字节序(大端字节序),我们为每个属性定义一个
    依赖于机器字节序的比特位解释 */
# include <endian.h>
# if __BYTE_ORDER == __BIG_ENDIAN  /* 如果是大端字节序 */
#  define _ISbit(bit)	(1 << (bit))
# else /* 否则__BYTE_ORDER==__LITTLE_ENDIAN,是小端字节序 */
#  define _ISbit(bit)	((bit) < 8 ? ((1 << (bit)) << 8) : ((1 << (bit)) >> 8))
# endif
enum
{
  _ISupper = _ISbit (0),	/* 大写字母字符A~Z:0x41~0x5A  */
  _ISlower = _ISbit (1),	/* 小写字母字符a~z:0x61~0x7A  */
  _ISalpha = _ISbit (2),	/* 字母字符A~Za~z  */
  _ISdigit = _ISbit (3),	/* 十进制数字字符0~9:0x30~0x39  */
  _ISxdigit = _ISbit (4),	/* 十六进制数字字符0~9A~Fa~f  */
  _ISspace = _ISbit (5),	/* 空白字符:0x9~0xD,0x20。包括水平制表符/t,换行符/n,
                                       垂直制表符/v,换页符/f,回车符/r,空格符' '  */
  _ISprint = _ISbit (6),	/* 可打印字符:0x20~0x7E。即任何非控制字符  */
  _ISgraph = _ISbit (7),	/* 图形字符:除空格以外的可打印字符  */
  _ISblank = _ISbit (8),	/* 空白分隔符:通常是空格符和水平制表符(Space和Tab键)  */
  _IScntrl = _ISbit (9),	/* 控制字符:0x0~0x1F,0x7F  */
  _ISpunct = _ISbit (10),	/* 标点符号  */
  _ISalnum = _ISbit (11)	/* 字母和数字字符  */
};
#endif /* ! _ISbit  */
/* 这些函数定义在ctype-info.c中。这里的描述必须与localeinfo.h中的一致。
    在依赖于线程的区域模型中(参看<local.h>中的uselocale),我们不能像过去那样对这些
    函数使用全局变量,现在这些访问函数返回每个变量的地址,这是多线程环境中当前线程的本
    地地址。
    这些指针指向一个大小为384的数组中,因此它们可以通过以下几种下标值来访问:任何[0,255]内的
   unsigend char值;EOF(-1);任何[-128,-1)内的signed char值。ISO C要求ctype中
    的函数工作在unsigend char或EOF上;这里我们同时也支持负的signed char值以兼容老的程序。
    大小写转换数组是int的,而不是unsigned char,因为tolower(EOF)的结果必须是EOF,这并不
    是一个unsigned char。但是今天更重要的是数组也会在多字节字符集中使用 */
extern __const unsigned short int **__ctype_b_loc (void)
     __attribute__ ((__const));
extern __const __int32_t **__ctype_tolower_loc (void)
     __attribute__ ((__const));
extern __const __int32_t **__ctype_toupper_loc (void)
     __attribute__ ((__const));
#define __isctype(c, type) /
  ((*__ctype_b_loc ())[(int) (c)] & (unsigned short int) type)
#define	__isascii(c)	(((c) & ~0x7f) == 0) /* 如果C是一个7比特的值,说明是一个ascii字符(0~127)  */
#define	__toascii(c)	((c) & 0x7f)		/* 屏蔽掉高位  */
/* 用宏来声明ctype中的各个函数原型,以简化代码 */
#define	__exctype(name)	extern int name (int) __THROW
__BEGIN_NAMESPACE_STD
/* 下面的名称是所有的函数:
   int isCHARACTERISTIC(int c); 
   当且仅当C有属性CHARACTERISTIC时返回非0值(真), 
   对CHARACTERISTIC名称的含义,参看上面的enum
   函数形参是一个字符,用int类型描述 */
__exctype (isalnum);  /* 这里是各个函数原型声明 */
__exctype (isalpha);
__exctype (iscntrl);
__exctype (isdigit);
__exctype (islower);
__exctype (isgraph);
__exctype (isprint);
__exctype (ispunct);
__exctype (isspace);
__exctype (isupper);
__exctype (isxdigit);
/* 返回C的小写形式  */
extern int tolower (int __c) __THROW;
/* 返回C的大写形式  */
extern int toupper (int __c) __THROW;
__END_NAMESPACE_STD

/* ISO C99引入了一个新函数  */
#ifdef	__USE_ISOC99
__BEGIN_NAMESPACE_C99
__exctype (isblank);
__END_NAMESPACE_C99
#endif
#ifdef __USE_GNU
/* 根据掩码MASK来测试C是否属于某个字符集  */
extern int isctype (int __c, int __mask) __THROW;
#endif
#if defined __USE_SVID || defined __USE_MISC || defined __USE_XOPEN
/* 返回非0值,当且仅当C是ASCII字符集中(例如,不足7比特的宽度)  */
extern int isascii (int __c) __THROW;
/* 返回C中在ASCII字符集中的那部分(例如,C的低位7比特)  */
extern int toascii (int __c) __THROW;
/* 下面的原型与toupper和tolower相同,唯一不同的它们不检查实参是否在char的范围内 */
__exctype (_toupper);
__exctype (_tolower);
#endif /* Use SVID or use misc.  */
/* 下面代码用于优化的转换函数中 */
#define __tobody(c, f, a, args) /
  (__extension__							      /
   ({ int __res;							      /
      if (sizeof (c) > 1)						      /
	{								      /
	  if (__builtin_constant_p (c))					      /
	    {								      /
	      int __c = (c);						      /
	      __res = __c < -128 || __c > 255 ? __c : (a)[__c];		      /
	    }								      /
	  else								      /
	    __res = f args;						      /
	}								      /
      else								      /
	__res = (a)[(int) (c)];						      /
      __res; }))
#if !defined __NO_CTYPE && !defined __cplusplus
# define isalnum(c)	__isctype((c), _ISalnum)
# define isalpha(c)	__isctype((c), _ISalpha)
# define iscntrl(c)	__isctype((c), _IScntrl)
# define isdigit(c)	__isctype((c), _ISdigit)
# define islower(c)	__isctype((c), _ISlower)
# define isgraph(c)	__isctype((c), _ISgraph)
# define isprint(c)	__isctype((c), _ISprint)
# define ispunct(c)	__isctype((c), _ISpunct)
# define isspace(c)	__isctype((c), _ISspace)
# define isupper(c)	__isctype((c), _ISupper)
# define isxdigit(c)	__isctype((c), _ISxdigit)
# ifdef __USE_ISOC99
#  define isblank(c)	__isctype((c), _ISblank)
# endif
# ifdef __USE_EXTERN_INLINES
__extern_inline int
__NTH (tolower (int __c))
{
  return __c >= -128 && __c < 256 ? (*__ctype_tolower_loc ())[__c] : __c;
}
__extern_inline int
__NTH (toupper (int __c))
{
  return __c >= -128 && __c < 256 ? (*__ctype_toupper_loc ())[__c] : __c;
}
# endif
# if __GNUC__ >= 2 && defined __OPTIMIZE__ && !defined __cplusplus
#  define tolower(c)	__tobody (c, tolower, *__ctype_tolower_loc (), (c))
#  define toupper(c)	__tobody (c, toupper, *__ctype_toupper_loc (), (c))
# endif /* Optimizing gcc */
# if defined __USE_SVID || defined __USE_MISC || defined __USE_XOPEN
#  define isascii(c)	__isascii (c)
#  define toascii(c)	__toascii (c)
#  define _tolower(c)	((int) (*__ctype_tolower_loc ())[(int) (c)])
#  define _toupper(c)	((int) (*__ctype_toupper_loc ())[(int) (c)])
# endif
#endif /* Not __NO_CTYPE.  */
/* 下面是GNU对各个属性分类函数和转换函数的扩展接口,每个函数有一个对应的扩展版本,
    增加了一个参数用来传递区域设置 */
    
/* ...... */
__END_DECLS
#endif /* ctype.h  */

/* ctype.c:各个字符处理函数的实现  */
#define	__NO_CTYPE
#include <ctype.h>
/* 为所有的ctype宏提供实际的函数实现  */
#define	func(name, type) /
  int name (int c) { return __isctype (c, type); }
func (isalnum, _ISalnum)
func (isalpha, _ISalpha)
func (iscntrl, _IScntrl)
func (isdigit, _ISdigit)
func (islower, _ISlower)
func (isgraph, _ISgraph)
func (isprint, _ISprint)
func (ispunct, _ISpunct)
func (isspace, _ISspace)
func (isupper, _ISupper)
func (isxdigit, _ISxdigit)
#define __ctype_tolower /
  ((int32_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_TOLOWER) + 128)
#define __ctype_toupper /
  ((int32_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_TOUPPER) + 128)
int
tolower (int c)
{
  return c >= -128 && c < 256 ? __ctype_tolower[c] : c;
}
int
toupper (int c)
{
  return c >= -128 && c < 256 ? __ctype_toupper[c] : c;
}

    解释:
    (1)字符的所有属性类被封装在一个enum中,每个属性对应一个枚举常量。
    (2)在作为接口的头文件中,由于各个函数的类型相同,都接受int型字符,返回int型的值,因此原型声明可用宏__exctype(name)来完成,name为函数名,这样可以简化代码。
    (3)所有的属性判断函数的实现都是用宏__isctype(c, type)和返回数组指针的外部函数__ctype_b_loc()来完成。在实现文件ctype.c中可以看到,所有的判断函数都只有一条语句“return __isctype (c, type);”。这个函数式宏用来判断字符c是否具有属性type(为枚举常量),它直接以字符c为下标,获得__ctype_b_loc()数组相应位置处的元素,并与属性作逻辑与运算,若结果为非0,说明字符具有该属性,若结果为0则说明字符没有该属性。__ctype_b_loc()函数在glibc库的ctype-info.c文件中定义,它直接使用了glibc 2.0中已经实现的内置函数。可见,这里用宏来实现ctype,使之可以扩展,增加任意的属性。当然,我们也可以自己来实现这些属性函数,代码都很简单,只要判断其ASCII编码范围即可。
    (4)ctype.c中的tolower和toupper函数实现使用了宏__ctype_tolower,这个宏会被映射成一个数组。它直接根据字符c的范围__ctype_tolower[c]或c本身。
    (5)ctype.h下面的优化实现用于需要优化的环境中(比如用带优化选项的gcc来编译)。它直接把属性判断函数定义为宏,宏体就是__isctype (c, type)。定义成宏时就少了一层函数调用。tolower和toupper根据需要,或者用外部函数__ctype_tolower_loc()和__ctype_toupper_loc()来实现,并实现成内联函数;或者直接定义成宏,用这里定义的__tobody(c, f, a, args)来实现。这两者都差不多,因为内联函数也相当于具有宏的特征。
    (6)__BEGIN_DECLS/__END_DECLS宏用来表示数据结构、全局变量、函数原型声明的开始和结束。这类似于MFC中的BEGIN_MESSAGE_MAP/END_MESSAGE_MAP。__BEGIN_NAMESPACE_STD/__END_NAMESPACE_STD宏表示C标准库函数原型声明的开始和结束。__BEGIN_NAMESPACE_C99/__END_NAMESPACE_C99表示C99标准中的函数声明。
   2、wctype.h: C89增补1中引入,是ctype.h中各个函数的宽字符处理版本,能对宽字符进行属性分类和转换。还定义了通用属性类型wctype_t,表示字符转换的类型wctrans_t,构造属性的函数wctype,测试属性的通用函数iswctype,构造转换的函数wctrans,实行转换的通用函数towctrans。

/* ISO C99 Standard: 7.25  宽字符分类和转换函数   <wctype.h>  */
#ifndef _WCTYPE_H
#include <features.h>
#include <bits/types.h>
#ifndef __need_iswxxx
# define _WCTYPE_H	1
/* 从<wchar.h>中获取wint_t类型  */
# define __need_wint_t
# include <wchar.h>
/* wint_t类型的常量表达式,其值不是扩展字符集的任何成员 */
# ifndef WEOF
#  define WEOF (0xffffffffu)
# endif
#endif
#undef __need_iswxxx
/* 当<wcsmbs.h>在Unix98兼容的代码中使用时,下面部分也会在<wcsmbs.h>头文件中被使用 */
#ifndef __iswxxx_defined
# define __iswxxx_defined	1
__BEGIN_NAMESPACE_C99
/* 标量类型,该类型的值表示特定区域字符的分类 */
typedef unsigned long int wctype_t; 
__END_NAMESPACE_C99
# ifndef _ISwbit
/* 这些属性总是被存储为网络字节序(大端字节)。我们为每个属性定义一个
    依赖于机器字节序的比特位解释 */
#  include <endian.h>
#  if __BYTE_ORDER == __BIG_ENDIAN
#   define _ISwbit(bit)	(1 << (bit))
#  else /* 否则__BYTE_ORDER==__LITTLE_ENDIAN,是小端字节序 */
#   define _ISwbit(bit)	/
	((bit) < 8 ? (int) ((1UL << (bit)) << 24)			      /
	 : ((bit) < 16 ? (int) ((1UL << (bit)) << 8)			      /
	    : ((bit) < 24 ? (int) ((1UL << (bit)) >> 8)			      /
	       : (int) ((1UL << (bit)) >> 24))))
#  endif
enum
{
  __ISwupper = 0,			/* 大写宽字符 */
  __ISwlower = 1,			/* 小写宽字符  */
  __ISwalpha = 2,			/* 字母宽字符  */
  __ISwdigit = 3,			/* 十进制数字宽字符  */
  __ISwxdigit = 4,			/* 十六进制数字宽字符  */
  __ISwspace = 5,			/* 空白宽字符  */
  __ISwprint = 6,			/* 可打印宽字符  */
  __ISwgraph = 7,			/* 图形宽字符  */
  __ISwblank = 8,			/* 空白分隔宽字符:通常是空格符和水平制表符(Space和Tab键)  */
  __ISwcntrl = 9,			/* 控制宽字符  */
  __ISwpunct = 10,			/* 标点符号宽字符  */
  __ISwalnum = 11,			/* 字母和数字宽字符  */
  _ISwupper = _ISwbit (__ISwupper),	/* UPPERCASE.  */
  _ISwlower = _ISwbit (__ISwlower),	/* lowercase.  */
  _ISwalpha = _ISwbit (__ISwalpha),	/* Alphabetic.  */
  _ISwdigit = _ISwbit (__ISwdigit),	/* Numeric.  */
  _ISwxdigit = _ISwbit (__ISwxdigit),	/* Hexadecimal numeric.  */
  _ISwspace = _ISwbit (__ISwspace),	/* Whitespace.  */
  _ISwprint = _ISwbit (__ISwprint),	/* Printing.  */
  _ISwgraph = _ISwbit (__ISwgraph),	/* Graphical.  */
  _ISwblank = _ISwbit (__ISwblank),	/* Blank (usually SPC and TAB).  */
  _ISwcntrl = _ISwbit (__ISwcntrl),	/* Control character.  */
  _ISwpunct = _ISwbit (__ISwpunct),	/* Punctuation.  */
  _ISwalnum = _ISwbit (__ISwalnum)	/* Alphanumeric.  */
};
# endif /* Not _ISwbit  */

__BEGIN_DECLS
__BEGIN_NAMESPACE_C99
/*
 * 宽字符分类函数: 7.15.2.1.
 */
/* 测试c是否是字母或数字宽字符,等价于iswalpha(c) || iswdigit(c) */
extern int iswalnum (wint_t __wc) __THROW;
/* 测试c是否是特定区域设置的字母宽字符,在iswlower(c)或isupper(c)为真时取值为真,
    在iswcntrl(c),iswdigit(c),iswpunct(c)或iswspace(c)为真时取值为假 */
extern int iswalpha (wint_t __wc) __THROW;
/* 测试是否是控制型的宽字符  */
extern int iswcntrl (wint_t __wc) __THROW;
/* 测试是否是十进制的数字宽字符  */
extern int iswdigit (wint_t __wc) __THROW;
/* 测试是否是图形宽字符,等价于iswprint(c) && !iswspace(c)  */
extern int iswgraph (wint_t __wc) __THROW;
/* 测试是否是小写宽字符,等价于!iswcntrl(c) && !iswdigit(c) && !iswpunct(c) 
   && !iswspace(c) */
extern int iswlower (wint_t __wc) __THROW;
/* 测试是否是可打印宽字符  */
extern int iswprint (wint_t __wc) __THROW;
/* 测试是否是标点符号宽字符,等价于iswprint(c) && !iswalnum(c) && !iswspace(c)  */
extern int iswpunct (wint_t __wc) __THROW;
/* 测试是否是空白宽字符,等价于!iswalnum(c) && !iswgraph(c) && !ispunct(c)  */
extern int iswspace (wint_t __wc) __THROW;
/* 测试是否是大写宽字符,等价于!iswcntrl(c) && !iswdigit(c) && !iswpunct(c) 
   && !iswspace(c) */
extern int iswupper (wint_t __wc) __THROW;
/* 测试是否是十六进制的数字宽字符  */
extern int iswxdigit (wint_t __wc) __THROW;
/* 测试是否是空白分隔宽字符  */
# ifdef __USE_ISOC99
extern int iswblank (wint_t __wc) __THROW;
# endif
/*
 * 可扩展的宽字符分类函数: 7.15.2.2.
 */
/* 构造一个wctype_t类型的值,表示由字符串PROPERTY标识的宽字符类 */
extern wctype_t wctype (__const char *__property) __THROW;
/* 确定宽字符WC是否是DESC所标识的宽字符类 */
extern int iswctype (wint_t __wc, wctype_t __desc) __THROW;
__END_NAMESPACE_C99
/*
 * 宽字符的大小写转换函数: 7.15.3.1.
 */
__BEGIN_NAMESPACE_C99
/* 标量类型,该类型的值表示特定区域的宽字符转换 */
typedef __const __int32_t *wctrans_t;
__END_NAMESPACE_C99
#ifdef __USE_GNU
__USING_NAMESPACE_C99(wctrans_t)
#endif
__BEGIN_NAMESPACE_C99
/* 把大写宽字符转换成对应的小写宽字符  */
extern wint_t towlower (wint_t __wc) __THROW;
/* 把小写宽字符成对应的大写宽字符 */
extern wint_t towupper (wint_t __wc) __THROW;
__END_NAMESPACE_C99
__END_DECLS
#endif	/* need iswxxx.  */

/* 剩下的定义和声明一定不能出现在<wcsmbs.h>中 */
#ifdef _WCTYPE_H
/*
 * 可扩展的宽字符转换函数: 7.15.3.2.
 */
__BEGIN_DECLS
__BEGIN_NAMESPACE_C99
/* 构造一个wctrans_t类型的值,表示由字符串PROPERTY标识的宽字符转换 */
extern wctrans_t wctrans (__const char *__property) __THROW;
/* 使用DESC所示的转换来对宽字符WC进行转换 */
extern wint_t towctrans (wint_t __wc, wctrans_t __desc) __THROW;
__END_NAMESPACE_C99
/* 下面是GNU对各个分类函数和转换函数的扩展接口,每个函数有一个对应的扩展版本,
    增加了一个参数用来传递区域设置 */
    
/* ...... */
__END_DECLS
#endif	/* __WCTYPE_H defined.  */
#endif /* wctype.h  */

/* wcfuncs.c:各个宽字符处理函数的实现 */
#include <ctype.h>
#include <wctype.h>
#include <locale/localeinfo.h>
#include "wchar-lookup.h"
/* 为所有wctype的原型提供实际的函数实现  */
#define	func(name, type)						      /
  extern int __isw##name (wint_t __wc);					      /
  int									      /
  __isw##name (wint_t wc)						      /
  {									      /
    if (isascii (wc))							      /
      return is##name ((int) wc);					      /
    size_t i = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_CLASS_OFFSET) + type;    /
    const char *desc = _NL_CURRENT (LC_CTYPE, i);			      /
    return wctype_table_lookup (desc, wc);				      /
  }									      /
  weak_alias (__isw##name, isw##name)
#undef iswalnum
func (alnum, __ISwalnum)
libc_hidden_weak (iswalnum)
#undef iswalpha
func (alpha, __ISwalpha)
libc_hidden_weak (iswalpha)
#undef iswblank
func (blank, __ISwblank)
#undef iswcntrl
func (cntrl, __ISwcntrl)
#undef iswdigit
func (digit, __ISwdigit)
libc_hidden_weak (iswdigit)
#undef iswlower
func (lower, __ISwlower)
libc_hidden_weak (iswlower)
#undef iswgraph
func (graph, __ISwgraph)
#undef iswprint
func (print, __ISwprint)
#undef iswpunct
func (punct, __ISwpunct)
#undef iswspace
func (space, __ISwspace)
libc_hidden_weak (iswspace)
#undef iswupper
func (upper, __ISwupper)
#undef iswxdigit
func (xdigit, __ISwxdigit)
libc_hidden_weak (iswxdigit)
#undef towlower
/* towlower函数的实现 */
wint_t
towlower (wc)
     wint_t wc;
{
  /* 获取区域设置表中当前区域类别的索引 */
  size_t i = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_OFFSET) + __TOW_tolower;
  /* 根据索引,获取当前区域设置类别的描述字符串 */
  const char *desc = _NL_CURRENT (LC_CTYPE, i);
  return wctrans_table_lookup (desc, wc); /* 搜索位表,以获得转换后的宽字符,并返回 */
}
libc_hidden_def (towlower)
#undef towupper
/* towupper函数的实现 */
wint_t
towupper (wc)
     wint_t wc;
{
  /* 获取区域设置表中当前区域类别的索引 */
  size_t i = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_OFFSET) + __TOW_toupper;
  /* 根据索引,获取当前区域设置类别的描述字符串 */
  const char *desc = _NL_CURRENT (LC_CTYPE, i);
  return wctrans_table_lookup (desc, wc); /* 搜索位表,以获得转换后的宽字符,并返回 */
}
libc_hidden_def (towupper)

   解释:
   (1)wctype.h的实现更通用,它定义一个描述宽字符属性的类型wctype_t,为unsigned long标量类型,实现了可扩展的、特定区域设置的宽字符分类功能。同样它也把所有属性类封装在一个enum中,每个属性对应一个枚举常量。wctype函数用来构造一个字符属性,参数为标识这个属性的字符串,主要有"alnum"、"alpha"、 "cntrl"、"digit"、"graph"、"lower"、"print"等,对应iswxxx属性分类函数。iswctype函数测试宽字符WC是否属于DESC属性类。调用iswctype时LC_CTYPE类别的设置应与wctype构造desc值时的LC_CTYPE设置相同。
   (2)宽字符集的分类取决于区域设置,其标准属性类映射到ASCII中的关系要理清楚:
   字母或数字 = 字母 || 数字
   大(小)写字母 = !控制字符 && !数字 && !标点符号 && !空白字符
   字母 = (大写字母 || 小写字母) && !控制字符 && !数字 && !标点符号 && !空白字符  
   图形字符 = 可打印字符 && !空格
   标点符号 = 可打印字符 && !字母 && !数字 && !空白字符
   空白字符 = !字母 && !数字 && !图形字符 && !标点符号
   (3)对字符属性的转换,wctype.h也定义了一个描述宽字符转换的类型wctrans_t,为32位整型指针。wctrans函数用来构造一个字符转换,参数为标识这个转换的字符串,主要有"tolower"、"toupper",对应towxxx转换函数,这个转换针对当前区域设置的LC_CTYPE类别值。towctrans函数使用DESC所示的转换来对宽字符WC进行转换。
   (4)在函数实现文件wcfuncs.c中,同样用了一个宏func(name, type)来简化实现。实现代码主要用到了_NL_CURRENT_WORD宏、LC_CTYPE类别宏、NL_CTYPE_MAP_OFFSET偏移宏。这些宏的功能在编译器内部或其附带的库中实现了。wctrans_table_lookup函数在wchar-lookup.h中定义,用于查询映射表,以获得转换后的宽字符。映射表有点类似于Unix的文件结构,用32位的字作为下标索引。宽字符集的每个字符被切割成4个比特块存储在位表的前面表项中,后面的几个表项存放了一级子表、二级子表、以及三级子表的指针。

转载于:https://my.oschina.net/abcijkxyz/blog/723077

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值