printf与wprintf不能同时混合使用的原因
2014-07-14 21:20
399 查看
具体参见http://www.gnu.org/savannah-checkouts/gnu/libc/manual/html_node/Streams-and-I18N.html
ISO C90 introduced the new type
strings using
The Unix standard early on (I think in XPG4.2) introduced two additional format specifiers for the
was made possible using the
type and that the wide character and string are transformed into/from multibyte strings before being used.
This was a beginning but it is still not good enough. Not always is it desirable to use
it is not possible to have a format string for
In the Amendment 1 to ISO C90 a whole new set of functions
was added to solve the problem. Most of the stream functions got a counterpart which take a wide character or wide character string instead of a character or string respectively. The new functions operate on the same streams (like
is different from the model of the C++ runtime library where separate streams for wide and normal I/O are used.
Being able to use the same stream for wide and normal operations
comes with a restriction: a stream can be used either for wide operations or for normal operations. Once it is decided there is no way back. Only a call to
can be decided in three ways:
If any of the normal character functions is used (this includes the
If any of the wide character functions is used the stream is marked as wide oriented.
The
It is important to never mix the use of wide and not wide operations on a stream. There are no diagnostics issued. The application behavior will simply be strange or the application will simply crash. The
can help avoiding this.
— Function: int fwide (FILE *stream, int mode)
Preliminary: | MT-Safe | AS-Unsafe corrupt | AC-Unsafe lock | See POSIX Safety Concepts.
The
possible to overwrite previous orientations with
If mode is zero the current orientation state is queried and nothing is changed.
The
This function was introduced in Amendment 1 to ISO C90 and is declared in wchar.h.
It is generally a good idea to orient a stream as early as possible. This can prevent surprise especially for the standard streams
function in some situations uses one of these streams and this use orients the stream in a different way the rest of the application expects it one might end up with hard to reproduce errors. Remember that no errors are signal if the streams are used incorrectly.
Leaving a stream unoriented after creation is normally only necessary for library functions which create streams which can be used in different contexts.
When writing code which uses streams and which can be used in different contexts it is important to query the orientation of the stream before using it (unless the rules of the library interface demand a specific
orientation). The following little, silly function illustrates this.
Note that in this case the function
The encoding used for the
directly to the stream. This is not what follows from the ISO C locale model either. What happens instead is that the bytes read from or written to the underlying media are first converted into the internal encoding chosen by the implementation for
The external encoding is determined by the
How and when the conversion happens is unspecified and it happens invisible to the user.
Since a stream is created in the unoriented state it has at that point no conversion associated with it. The conversion which will be used is determined by the
the stream is oriented. If the locales are changed at the runtime this might produce surprising results unless one pays attention. This is just another good reason to orient the stream explicitly as soon as possible, perhaps with a call to
ISO C90 introduced the new type
wchar_tto allow handling larger character sets. What was missing was a possibility to output strings of
wchar_tdirectly. One had to convert them into multibyte
strings using
mbstowcs(there was no
mbsrtowcsyet) and then use the normal stream functions. While this is doable it is very cumbersome since performing the conversions is not trivial and greatly increases program complexity and size.
The Unix standard early on (I think in XPG4.2) introduced two additional format specifiers for the
printfand
scanffamilies of functions. Printing and reading of single wide characters
was made possible using the
%Cspecifier and wide character strings can be handled with
%S. These modifiers behave just like
%cand
%sonly that they expect the corresponding argument to have the wide character
type and that the wide character and string are transformed into/from multibyte strings before being used.
This was a beginning but it is still not good enough. Not always is it desirable to use
printfand
scanf. The other, smaller and faster functions cannot handle wide characters. Second,
it is not possible to have a format string for
printfand
scanfconsisting of wide characters. The result is that format strings would have to be generated if they have to contain non-basic characters.
In the Amendment 1 to ISO C90 a whole new set of functions
was added to solve the problem. Most of the stream functions got a counterpart which take a wide character or wide character string instead of a character or string respectively. The new functions operate on the same streams (like
stdout). This
is different from the model of the C++ runtime library where separate streams for wide and normal I/O are used.
Being able to use the same stream for wide and normal operations
comes with a restriction: a stream can be used either for wide operations or for normal operations. Once it is decided there is no way back. Only a call to
freopenor
freopen64can reset the orientation. The orientation
can be decided in three ways:
If any of the normal character functions is used (this includes the
freadand
fwritefunctions) the stream is marked as not wide oriented.
If any of the wide character functions is used the stream is marked as wide oriented.
The
fwidefunction can be used to set the orientation either way.
It is important to never mix the use of wide and not wide operations on a stream. There are no diagnostics issued. The application behavior will simply be strange or the application will simply crash. The
fwidefunction
can help avoiding this.
— Function: int fwide (FILE *stream, int mode)
Preliminary: | MT-Safe | AS-Unsafe corrupt | AC-Unsafe lock | See POSIX Safety Concepts.
The
fwidefunction can be used to set and query the state of the orientation of the stream stream. If the mode parameter has a positive value the streams get wide oriented, for negative values narrow oriented. It is not
possible to overwrite previous orientations with
fwide. I.e., if the stream stream was already oriented before the call nothing is done.
If mode is zero the current orientation state is queried and nothing is changed.
The
fwidefunction returns a negative value, zero, or a positive value if the stream is narrow, not at all, or wide oriented respectively.
This function was introduced in Amendment 1 to ISO C90 and is declared in wchar.h.
It is generally a good idea to orient a stream as early as possible. This can prevent surprise especially for the standard streams
stdin,
stdout, and
stderr. If some library
function in some situations uses one of these streams and this use orients the stream in a different way the rest of the application expects it one might end up with hard to reproduce errors. Remember that no errors are signal if the streams are used incorrectly.
Leaving a stream unoriented after creation is normally only necessary for library functions which create streams which can be used in different contexts.
When writing code which uses streams and which can be used in different contexts it is important to query the orientation of the stream before using it (unless the rules of the library interface demand a specific
orientation). The following little, silly function illustrates this.
void print_f (FILE *fp) { if (fwide (fp, 0) > 0) /* Positive return value means wide orientation. */ fputwc (L'f', fp); else fputc ('f', fp); }
Note that in this case the function
print_fdecides about the orientation of the stream if it was unoriented before (will not happen if the advise above is followed).
The encoding used for the
wchar_tvalues is unspecified and the user must not make any assumptions about it. For I/O of
wchar_tvalues this means that it is impossible to write these values
directly to the stream. This is not what follows from the ISO C locale model either. What happens instead is that the bytes read from or written to the underlying media are first converted into the internal encoding chosen by the implementation for
wchar_t.
The external encoding is determined by the
LC_CTYPEcategory of the current locale or by the ‘ccs’ part of the mode specification given to
fopen,
fopen64,
freopen, or
freopen64.
How and when the conversion happens is unspecified and it happens invisible to the user.
Since a stream is created in the unoriented state it has at that point no conversion associated with it. The conversion which will be used is determined by the
LC_CTYPEcategory selected at the time
the stream is oriented. If the locales are changed at the runtime this might produce surprising results unless one pays attention. This is just another good reason to orient the stream explicitly as soon as possible, perhaps with a call to
fwide.
相关文章推荐
- Android AlertDialog 设置setSingleChoiceItems不显示列表的原因【setMessage和setSingleChoiceItems不能同时使用】
- abstract与static、synchronized、native不能同时使用的原因
- FC6 中串口不能正常使用的原因与解决办法
- 使用IE不能访问ftp的原因
- 使用PeekMessage后,调用postquitmessage(0)不能退出消息循环的原因
- 使用cvs的时候,WEB-INF/classes中不能编译生成class文件的原因?
- 解决QQ与360安全卫士不能同时使用绝妙方法
- 项目开发不能没有开发文档,同时要降低开发文档的使用和管理成本
- 请把从1到1000的数打印出来,但你不能使用任何的循环语句或是条件语句。更不能写1000个printf
- 使用hibernate与mysql时数据不能插入的原因及解决办法
- 2009/12/11 Office 使用RMS 认证出现问题,office 不能开正常打开加密文档,同时不能再加密文档
- 不能使用Hibernate Reverse Engineering生成实体类的原因
- VB不能使用剪贴板的原因
- VAssistX不能使用的原因
- validator不能正常使用的原因
- 同时安装ASA10以及ASA11两个数据库导致不能使用SQLSERVER2005 management studio的问题解决
- CRichEditControl 不能正常使用的原因
- 一个HTML的低级错误!!!与不能同时使用
- Struts2 标签不能使用静态方法的原因
- Nokia论坛filelogger中不能直接使用的原因