数学建模社区-数学中国

标题: 关于wcslen的一个错觉! [打印本页]

作者: xShandow    时间: 2004-11-26 09:45
标题: 关于wcslen的一个错觉!
<>不知道大家有没有我这种体验.大家先看看下面这段代码:</P>4 A3 ]5 {( w  g
<>int fp=_wopen(L"Hello.dat",O_BINARY | O_CREAT | O_TRUNC | O_RDWR);
- ?* c& R8 T$ m  l2 |: Qif(fp==-1) return;" ]7 A# Y& r$ z  `6 P' T
write(fp,L"123中国人",wcslen(L"123中国人"));- p: ]. e) k* [* I! P
close(fp);
( Z, W6 Y4 E7 A+ |0 \6 a2 Z4 X0 k# e$ w+ {% v
上面这段代码不知道大家看出什么BUG来了.如果大家看不出毛病也不足为怪,因为这是我们的习惯导致了我们的错误产生.
$ E3 f2 P, K5 f8 |) Y1 e- b" J  h$ O% g; W$ b' h
先让我来分析一下write吧.下面是write的原型:) j# u+ Z9 O4 \/ i& K  H  y, B! h% K. l
int write( int <I>handle</I>, const void *<I>buffer</I>, unsigned int <I>count</I> );- y! d5 B) P/ }4 M, Z) _! y, O, s; i# m6 ~

! [1 t, O" P: T, v& p参数:
* |3 V& j, U* S' G+ f/ w3 Jhandle   已打开或已创建的文件句柄
: p4 O) Z* Z$ K5 B5 `  @buffer     待写入的数据
. k$ h  l8 F5 X5 Scount     待写入的数据大小
) @& c  t# e5 |! x9 @$ t* y9 T% Y& ^  h0 I
现在分析为什么上面的那代码有bug,其实主要问题就在一个buffer,和count.# F! {6 F, k" @7 N$ a
如果我们写入一个Ansi字符串,上面的代码改成相应的形式确实没有错.% i# s$ a4 ~) \, e
但如果是写入一个宽字符串,那么上面的代码就不严格.原因就在于count.
. k3 @( X, \) N2 m- V% j
/ ^3 `4 Y) C& W我们首先看一下strlen和wcslen,如果使用strlen,一般情况下,我们直接作为字符串的长度,
/ J; }( U' V; T4 O而使用wcslen,你会发现,得出的不是字符串的长度而是字符的个数.
' G* w+ G$ h3 b5 s! C$ a  d
, k- u/ a* l; `" {. Z' P* _这就是问题的所在.一般情况下.char的长度是1,这是用sizeof(char)运算出来的结果.+ H/ J% e, \' @
len=strlen(str)*sizeof(char);而我们一般情况下,都只用strlen(str)来等价,这就是平时的习惯.
+ q% q* _$ @/ s( q5 s2 @( T2 H# i正是由于这个习惯所引来的问题,这个习惯并不适用于宽字符串.因为wcslen(str)*sizeof(wchar_t)并不等于wcslen(strl).这就是习惯所引起的错误.
% [$ }8 ]' F" b2 u3 ~0 z  `/ `6 ]* [$ j& X
说到这里我想大家都明白了.我在这里把这种习惯称之为不良习惯.所以大家以后在计算字符串长度的时候,千万不能简而简之,一定要len=strlen(str)*sizeof(char),len=wcslen(str)*sizeof(wchar_t).& R# |3 X$ u, S" z" J
不要再犯这种习惯性的低级错误.(在下就犯了这种错误.大家都可怜我吧!).</P>
3 Y! U. _$ J1 M
[此贴子已经被作者于2004-11-26 9:50:40编辑过]

作者: ilikenba    时间: 2004-12-2 15:50
欧!我也是一直那样想当然的用了!
作者: xShandow    时间: 2004-12-2 17:55
我被这个错误折磨了好半天。




欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5