都是'\0'惹的祸——中兴一道关于字符串的笔试题详解

另记(2011-09-26):我之前的想法还是有问题,感谢大家的批评指正,这篇文章的看点还是下面的评论,谢谢各路大神。

〇、引子

  上周日下午参加了中兴的笔试(详细笔试内容见我之前的博文《中兴笔试归来总结(2012软件类)》),其中有道题是这样的:

  找出下列程序的错误

void Test( char *str1 ) 
1 void Test( char *str1 )
2 {
3   char string[10];
4   if( strlen(str1) <= 10 )
5 {
6    strcpy( string, str1 );
7 }
8 }

  这个题乍一看除了这个函数没什么实际用途以外没什么错误(其实那也不算是错误),即使你用VC之类的编译运行不仔细的话也不会发现任何问题。
  再通读下这个函数,可以发现以下2点值得推敲:
  ①char *str1输入的实参可能是一个指针,有可能是一个数组,正是由于这点才导致以下可能出现的问题;
  ②strlen()对输入不同(是指针或是数组)时会不会有不同;
  下面就对以上三点一个一个的进行剖析,找出真正的“凶手”。

一、作为形参的指针

  大家都知道,当指针作为形参时,它对应的实参可能是一个指针,也可能是一个数组,你可能会认为在这点上指针和函数是等价的,但当真就是等价的么?用指针作为形参输入函数,和用数组作为形参输入数组,它们之间真的是完全等价,没有任何不同吗?我想,你可能想错了,只有这么个说法:当作为形参时,指针和数组是等价的,也就是函数采用
void Test( char *str )

void Test( char str[] )
这两种形式,它们代表的意思是相同的,没有任何差别。

  稍微说远了点,下面言归正传,经过上面的这几句可能你还不是很相信,那么我们来做个试验,证明下到底当对一个函数输入指针和输入数组会不会不同。

View Test Code
 1 #include <stdio.h>
2 #include <string.h>
3
4 void Test2( char *str1, char *str2 );
5
6 int main()
7 {
8 char *str1="abcdefgh";
9 char str2[8]="abcdefgh";
10 Test2(str1, str2);
11 return 0;
12 }
13
14 void Test2( char *str1, char *str2 )
15 {
16 printf( "str1:%s\r\nstr2:%s\r\n", str1, str2 );
17 }

  以上这个测试程序打印出来的结果是
str1:abcdefgh
str2:abcdefgh( B
  事实证明,两者还是有不同的,按照之前的理解,其打印结果应该是一样的啊,怎么str2会出现后面的乱码呢?也就是说str2的长度本来应该是和str1的相同的,这是为什么呢?先把这个疑问留在这里,看完下面的大家可能就清楚了。

二、字符串测长函数strlen()
  字符串测长函数strlen是属于标准库string.h中的一个函数,其返回值是字符串中的实际长度,而这个实际长度的意思就是不包括字符串结束标志'\0'在内,而对一个字符串进行长度测试时,在碰到字符串结束标志'\0'时就认为该字符串已经测完,这样就可以解释为什么字符串"abc\0abc"的长度返回值为3了。
  下面我们又回到上面那个例子,无论%s和strlen以及其他一些关于字符串的函数,都跟'\0'有莫大的关系,所以刚才打印的时候肯定是本应该存在的'\0'因为某些原因丢失了,然后一直打印到另外一个'\0',所以就出现了上面那个情况。

三、总结
  上面也把最开始提出那道题的要点说得差不多了,回到那道题分析下,当输入的字符串形式为str[10]="abcdeabcde",在Test函数中strlen(str)的值将大于10,不符合if判断条件,将不执行strcpy;而若输入字符串形式为*str="abcdeabcde",其长度刚好为10,符合if判断条件,将执行strcpy。这样,当字符串相同时,就出现了不同的执行结果,这便是这个程序的错误之处。

  为啥会这样呢?因为当输入为数组形式时,其传入到Test函数的只是"abcdeabcde",而没有'\0',这样自然strlen时会出现问题,若是把输入的字符串改成如下形式
str[11]="abcdeabcde";
这样,是可以执行到strcpy的,大家可以试试看。因为这个字符串其实就等价于"abcdeabcde\0",strlen是可以测到长度的。

  这样不难理解,为什么有些程序员在编程时在字符串末手动加上字符'\0'了,这样就不会出现一些类似这样的潜在问题了。

  以上只是个人浅薄的一些理解,若有理解不对误导大家的地方,还望不吝赐教。

posted @ 2011-09-22 17:20  云中箫  Views(3645)  Comments(33Edit  收藏  举报