【发布时间】:2017-03-28 20:26:37
【问题描述】:
wchar_t 定义在wchar.h
目前,如果开发者只想使用wchar_t,他们做不到
这没有从编译器获得类型转换警告。如果
wchar_t 将与wint_t 的类型相同,这对双方都有好处。
希望同时拥有wint_t 和wchar_t 的开发人员
程序(例如,如果他们希望他们的代码不仅在
glibc) 可以做到这一点而不会收到编译器警告。开发商们
只想使用wchar_t(以避免使用wint_t和
显式类型转换)也可以做到这一点而不会收到编译器警告。
而且它不会带来任何不兼容或可移植性问题,除非如果只使用wchar_t 的代码将在使用原始wchar.h 的机器上编译,编译器将打印那些讨厌的警告(如果启用了-Wconversion),但是编译后的程序将以完全相同的方式运行。
C 标准 (9899:201x 7.29) 提到:
wchar_t 和 wint_t 可以是相同的整数类型。
另外,在 glibc 中,宽字符总是
ISO10646/Unicode/UCS-4,所以它们总是使用 4 个字节。因此,什么都没有
防止在 glibc 中使 wchar_t 与 wint_t 的类型相同。
但似乎 glibc 的开发者不想让wint_t 和
wchar_t 出于某种原因是同一类型。因此,我想更改的本地副本
wchar.h.
ISO10646/Unicode/UCS-4 使用 2^31 值作为扩展字符集
(MSB 未使用):
0xxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
注意,一个 4 字节的类型可以保存 2^31 额外值(MSB 为“1”):
1xxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
任何这些额外的值都可以用来表示WEOF,因此一个
4字节类型可用于保存所有字符集和WEOF。
注意,使用修改后的wchar.h不需要重新编译glibc,因为
wint_t 可以有符号或无符号(因为 -1 和 0xffffffff 都有 MSB
“1”,在任何表示中,并且由于 MSB 不用于
ISO10646/Unicode/UCS-4)。
wchar_t 的定义在wchar.h 的以下摘录中完成。
如何更改它以使wchar_t 与wint_t 的类型相同?
#ifndef _WCHAR_H
#if !defined __need_mbstate_t && !defined __need_wint_t
# define _WCHAR_H 1
# include <features.h>
#endif
#ifdef _WCHAR_H
/* Get FILE definition. */
# define __need___FILE
# if defined __USE_UNIX98 || defined __USE_XOPEN2K
# define __need_FILE
# endif
# include <stdio.h>
/* Get va_list definition. */
# define __need___va_list
# include <stdarg.h>
# include <bits/wchar.h>
/* Get size_t, wchar_t, wint_t and NULL from <stddef.h>. */
# define __need_size_t
# define __need_wchar_t
# define __need_NULL
#endif
#if defined _WCHAR_H || defined __need_wint_t || !defined __WINT_TYPE__
# undef __need_wint_t
# define __need_wint_t
# include <stddef.h>
/* We try to get wint_t from <stddef.h>, but not all GCC versions define it
there. So define it ourselves if it remains undefined. */
# ifndef _WINT_T
/* Integral type unchanged by default argument promotions that can
hold any value corresponding to members of the extended character
set, as well as at least one value that does not correspond to any
member of the extended character set. */
# define _WINT_T
typedef unsigned int wint_t;
# else
/* Work around problems with the <stddef.h> file which doesn't put
wint_t in the std namespace. */
# if defined __cplusplus && defined _GLIBCPP_USE_NAMESPACES \
&& defined __WINT_TYPE__
__BEGIN_NAMESPACE_STD
typedef __WINT_TYPE__ wint_t;
__END_NAMESPACE_STD
# endif
# endif
/* Tell the caller that we provide correct C++ prototypes. */
# if defined __cplusplus && __GNUC_PREREQ (4, 4)
# define __CORRECT_ISO_CPP_WCHAR_H_PROTO
# endif
#endif
#if (defined _WCHAR_H || defined __need_mbstate_t) && !defined ____mbstate_t_defined
# define ____mbstate_t_defined 1
/* Conversion state information. */
typedef struct
{
int __count;
union
{
# ifdef __WINT_TYPE__
__WINT_TYPE__ __wch;
# else
wint_t __wch;
# endif
char __wchb[4];
} __value; /* Value so far. */
} __mbstate_t;
#endif
#undef __need_mbstate_t
/* The rest of the file is only used if used if __need_mbstate_t is not
defined. */
#ifdef _WCHAR_H
# ifndef __mbstate_t_defined
__BEGIN_NAMESPACE_C99
/* Public type. */
typedef __mbstate_t mbstate_t;
__END_NAMESPACE_C99
# define __mbstate_t_defined 1
# endif
#ifdef __USE_GNU
__USING_NAMESPACE_C99(mbstate_t)
#endif
#ifndef WCHAR_MIN
/* These constants might also be defined in <inttypes.h>. */
# define WCHAR_MIN __WCHAR_MIN
# define WCHAR_MAX __WCHAR_MAX
#endif
#ifndef WEOF
# define WEOF (0xffffffffu)
#endif
/* For XPG4 compliance we have to define the stuff from <wctype.h> here
as well. */
#if defined __USE_XOPEN && !defined __USE_UNIX98
# include <wctype.h>
#endif
__BEGIN_DECLS
__BEGIN_NAMESPACE_STD
/* This incomplete type is defined in <time.h> but needed here because
of `wcsftime'. */
struct tm;
__END_NAMESPACE_STD
/* XXX We have to clean this up at some point. Since tm is in the std
namespace but wcsftime is in __c99 the type wouldn't be found
without inserting it in the global namespace. */
__USING_NAMESPACE_STD(tm)
【问题讨论】:
-
顺便说一句,如果 glibc 开发人员添加一些关于使用什么
__need_wint_t、__need_mbstate_t、__WINT_T、__WINT__TYPE等的文档,那就不错了……我不能制作这个神秘代码的头部或尾部。
标签: c glibc wchar-t widechar wchar