数学建模社区-数学中国

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

作者: xShandow    时间: 2004-11-26 09:45
标题: 关于wcslen的一个错觉!
<>不知道大家有没有我这种体验.大家先看看下面这段代码:</P>
9 [2 o% x. i" s* J  i; c7 z<>int fp=_wopen(L"Hello.dat",O_BINARY | O_CREAT | O_TRUNC | O_RDWR);- i6 b5 ]1 M& @5 U+ g
if(fp==-1) return;' H* }8 H8 ^  A! [
write(fp,L"123中国人",wcslen(L"123中国人"));! T' {, G9 d' f4 g( E
close(fp);
: o1 D! D% P2 Q: ?* O4 o$ u  `/ E, V  w* U- C# R: [: N
上面这段代码不知道大家看出什么BUG来了.如果大家看不出毛病也不足为怪,因为这是我们的习惯导致了我们的错误产生.
+ ^" Y; U& B6 W5 H
) C9 x" y! v2 p' A先让我来分析一下write吧.下面是write的原型:
- S) V3 X5 m/ r7 E+ j5 ]' T0 Iint write( int <I>handle</I>, const void *<I>buffer</I>, unsigned int <I>count</I> );
; C8 P/ }$ ?2 K! @. t) Y. j4 {+ C+ |- w( f( v7 ^7 k2 X& b9 ?
参数:
) h5 j' Q/ c6 }9 ~3 X1 [% ]2 mhandle   已打开或已创建的文件句柄
7 E$ ~8 A- X6 I4 t0 [buffer     待写入的数据
1 P* F, u5 K/ t6 a  e% i# v$ Mcount     待写入的数据大小/ D; h# [$ [8 N1 C
7 H1 E- j- h% ~5 Q
现在分析为什么上面的那代码有bug,其实主要问题就在一个buffer,和count.+ Z8 A+ D+ `8 a$ a9 l  G5 f( W! @
如果我们写入一个Ansi字符串,上面的代码改成相应的形式确实没有错.; Y! \" V% d- z  L  S' G
但如果是写入一个宽字符串,那么上面的代码就不严格.原因就在于count.
0 i% |" J5 u" u
4 p) h# e9 T& A7 N+ B& J: r% g我们首先看一下strlen和wcslen,如果使用strlen,一般情况下,我们直接作为字符串的长度,
/ ]4 n1 m' X* G% W2 y而使用wcslen,你会发现,得出的不是字符串的长度而是字符的个数.+ q- k. {  O3 Y3 U4 W* K/ E" `

, V( c* j( k& d' z* a' k' K) v这就是问题的所在.一般情况下.char的长度是1,这是用sizeof(char)运算出来的结果.% p0 N4 g( J4 P0 s
len=strlen(str)*sizeof(char);而我们一般情况下,都只用strlen(str)来等价,这就是平时的习惯.
5 j. a, Q" m# t' d. i正是由于这个习惯所引来的问题,这个习惯并不适用于宽字符串.因为wcslen(str)*sizeof(wchar_t)并不等于wcslen(strl).这就是习惯所引起的错误.
+ W4 j% T; f$ P: b  u7 P* ?3 o. t3 I! [+ [8 I4 G& N9 n' j
说到这里我想大家都明白了.我在这里把这种习惯称之为不良习惯.所以大家以后在计算字符串长度的时候,千万不能简而简之,一定要len=strlen(str)*sizeof(char),len=wcslen(str)*sizeof(wchar_t).# I& e, R0 u" M, r$ t+ {/ ]
不要再犯这种习惯性的低级错误.(在下就犯了这种错误.大家都可怜我吧!).</P>( m; u: [/ R) X2 g( \  Y: @
[此贴子已经被作者于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