wchar_t 在puts $::foo($key)
目前,如果开发人员只想使用wchar.h
,他们就无法做到
这没有得到编译器的类型转换警告。如果
wchar_t
与wchar_t
的类型相同,对双方都有好处。
希望同时拥有wint_t
和wint_t
的开发人员
程序(例如,如果他们希望他们的代码不仅被编译
glibc)可以在不收到编译器警告的情况下执行此操作。开发人员
想只使用wchar_t
(以避免使用wchar_t
和使用时出现不必要的麻烦
显式类型转换)也可以在不获取编译器警告的情况下执行此操作。
并且它不会带来任何不兼容或可移植性问题,除非在使用原始wint_t
的机器上编译仅使用wchar_t
的代码,编译器将打印那些讨厌的警告(如果wchar.h
已启用),但编译的程序将以完全相同的方式工作。
C标准(9899:201x 7.29)提到:
wchar_t和wint_t可以是相同的整数类型。
另外,在glibc中,宽字符总是如此
ISO10646 / Unicode / UCS-4,因此它们总是使用4个字节。因此,没有
阻止使-Wconversion
与glibc中的wchar_t
类型相同。
但似乎glibc的开发人员不想制作wint_t
和
由于某种原因wint_t
相同的类型。因此,我想更改本地副本
wchar_t
。
ISO10646 / Unicode / UCS-4对扩展字符集使用wchar.h
值
(MSB未被使用):
2^31
请注意,4字节类型可以容纳0xxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
个额外值(MSB为" 1"):
2^31
任何这些额外值都可用于表示1xxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
,因此可以表示WEOF
4字节类型可用于保存所有字符集和 WEOF
。
请注意,使用修改后的wchar.h
不需要重新编译glibc,因为
wint_t
可以是已签名或未签名(因为-1
和0xffffffff
都有MSB
" 1",任何表示,并且因为没有使用MSB
ISO10646 /统一字符编码/ 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)
答案 0 :(得分:1)
请注意,我引入了wint_t
,因为wchar_t
在传递给printf()
等人时可能是受“默认促销”规则约束的类型。例如,在调用printf()
:
wchar_t wc = …;
printf("%lc", wc);
wc
的值可能会转换为wint_t
。如果您正在编写类似printf()
的函数,需要使用va_arg()
中的<stdarg.h>
宏,那么您应该使用类型wint_t
来获取值。
标准说明wint_t
可能与wchar_t
的类型相同,但如果wchar_t
是(16位)short
(或unsigned short
),wint_t
可能是(32位)int
。对于第一个近似值,wint_t
仅在wchar_t
为16位类型时才有意义。当然,完整的规则更复杂。例如,int
可能是16位类型 - 但这很少是一个问题。
7.29扩展的多字节和宽字符实用程序
<wchar.h>
7.29.1简介
¶1标题
<wchar.h>
定义了四个宏,并声明了四种数据类型,一个标记和 许多功能。 326)2声明的类型为
wchar_t
和size_t
(均在7.19中描述);mbstate_t
这是一个完整的对象类型,而不是可以保存转换状态的数组类型 在多字节字符和宽字符序列之间进行转换所需的信息 字符;
wint_t
这是一个整数类型,默认情况下,参数升级不变,可以保存任何 对应于扩展字符集成员的值,以及至少一个 与扩展字符集的任何成员不对应的值(请参阅
WEOF
下面); 327) ...326)参见“未来的图书馆方向”(7.31.16) 327)
wchar_t
和wint_t
可以是相同的整数类型。§7.19通用定义
<stddef.h>
¶2......和
wchar_t
是一个整数类型,其值范围可以表示所有的不同代码 受支持的语言环境中指定的最大扩展字符集的成员;该 null字符的代码值为零。基本字符集的每个成员 当用作整数中的单个字符时,其代码值应等于其值 如果实现没有定义,则为字符常量
__STDC_MB_MIGHT_NEQ_WC__
。
请参阅Why the argument type of putchar()
, fputc()
, and putc()
is not char
,了解引用C标准中“默认促销”规则的地方。可能还有其他问题可以获得信息。
答案 1 :(得分:0)
如果我们需要在使用-Wconversion
编译器选项时避免类型转换警告,我们需要在所有库函数的原型中将wint_t
更改为wchar_t
,并将&#39 ; #define WEOF(-1)&#39;到wchar.h
和wctype.h
对于wchar.h
,命令为:
sudo perl -i -pe 'print qq(#define WEOF (-1)\n) if $.==1; next unless /Copy SRC to DEST\./..eof; s/\bwint_t\b/wchar_t/g' /usr/include/wchar.h
对于wctype.h
,命令为:
sudo perl -i -pe 'print qq(#define WEOF (-1)\n) if $.==1; next unless /Wide-character classification functions/..eof; s/\bwint_t\b/wchar_t/g' /usr/include/wctype.h
同样,如果您使用其他使用wint_t
的标头文件,只需在这些标头文件的原型中将wint_t
更改为wchar_t
。
说明如下。
某些Unix系统将
wchar_t
定义为16位类型,因此非常严格地遵循Unicode。这个定义完全符合标准,但它也意味着要表示来自Unicode和ISO 10646的所有字符,必须使用UTF-16代理字符,这实际上是一个多宽字符编码。但是,采用多宽字符编码与wchar_t
类型的目的相矛盾。
现在,唯一能够在数据交换中存活的编码是UTF-8
,它可容纳的最大数据位数为31
:
1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
因此,您可以看到实际上没有必要将wint_t
作为单独的类型(因为4字节(即32位)数据类型用于存储 Unicode 代码点无论如何)。也许它有一些应用程序&#34;向后兼容性&#34;或者其他东西,但在新的代码中它是毫无意义的。再一次,因为它完全违背了拥有宽字符的目的(而且无法处理UTF-8,现在使用宽字符毫无意义。)
请注意,无论如何都不使用事实上的wint_t
。例如,请参阅man mbstowcs
中的示例。那里wchar_t
类型的变量传递给iswlower()
以及来自wctype.h
的其他函数,其中wint_t
。