数学建模社区-数学中国

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

作者: xShandow    时间: 2004-11-26 09:45
标题: 关于wcslen的一个错觉!
<>不知道大家有没有我这种体验.大家先看看下面这段代码:</P>& f% O5 C- |1 s5 d3 I6 \0 \0 N
<>int fp=_wopen(L"Hello.dat",O_BINARY | O_CREAT | O_TRUNC | O_RDWR);
7 G( B$ s- u. Xif(fp==-1) return;. h+ }3 j/ u$ D/ B* P
write(fp,L"123中国人",wcslen(L"123中国人"));
5 g7 _5 }, E; u0 [" B9 \9 Z0 \close(fp);' Y  e1 p( S# r
3 s8 }5 i- [8 H% g
上面这段代码不知道大家看出什么BUG来了.如果大家看不出毛病也不足为怪,因为这是我们的习惯导致了我们的错误产生.7 A. j: W1 ~# P0 p, `9 d3 m. N

7 d# f# ~( P. W先让我来分析一下write吧.下面是write的原型:! e: q, ~& d  }9 }2 p4 k: y& p
int write( int <I>handle</I>, const void *<I>buffer</I>, unsigned int <I>count</I> );
5 F9 e/ \: j/ _& {
" ^* S" k, ?" x' H3 v. j参数:
6 c9 k0 J3 U! j- S/ w5 Y5 Ahandle   已打开或已创建的文件句柄  J7 M0 d/ N7 [' }
buffer     待写入的数据
; y5 j3 U- g, P" l9 ^0 O& u" a$ _count     待写入的数据大小
( x3 n: K( b1 T. w
' F( _" j/ |$ T1 n) f现在分析为什么上面的那代码有bug,其实主要问题就在一个buffer,和count.
8 L. I" Y5 K  c3 P# R0 V* v如果我们写入一个Ansi字符串,上面的代码改成相应的形式确实没有错.
9 U- V" [% L* ^  d0 @但如果是写入一个宽字符串,那么上面的代码就不严格.原因就在于count.
  _6 w3 S- v6 M: W" G4 x, T5 |# S% j2 m, O' B
我们首先看一下strlen和wcslen,如果使用strlen,一般情况下,我们直接作为字符串的长度,
5 k' n% t+ `* _而使用wcslen,你会发现,得出的不是字符串的长度而是字符的个数.6 b& P, x( X  R, P6 p

; l* z4 B( g4 i: x7 Y, {. @这就是问题的所在.一般情况下.char的长度是1,这是用sizeof(char)运算出来的结果.
2 i: j! g. `% Blen=strlen(str)*sizeof(char);而我们一般情况下,都只用strlen(str)来等价,这就是平时的习惯.
- H' z6 W4 b; k; s正是由于这个习惯所引来的问题,这个习惯并不适用于宽字符串.因为wcslen(str)*sizeof(wchar_t)并不等于wcslen(strl).这就是习惯所引起的错误.
. W0 S5 R. l; R9 ~" h
- x$ b. A7 X9 @8 P说到这里我想大家都明白了.我在这里把这种习惯称之为不良习惯.所以大家以后在计算字符串长度的时候,千万不能简而简之,一定要len=strlen(str)*sizeof(char),len=wcslen(str)*sizeof(wchar_t).6 O0 C( N5 `1 @% v& p% R. o
不要再犯这种习惯性的低级错误.(在下就犯了这种错误.大家都可怜我吧!).</P>
5 d4 l% t8 u4 I. s8 P
[此贴子已经被作者于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