C语言中,字符串常量代表了一块包括字符串中所有字符以及一个空字符(’\0’)的内存区域的地址。因为C语言要求字符串常量以空字符作为结束标志,对于其他字符串,C程序员通常也沿用这一惯例。
假定我们有两个这样的字符串s和t,我们希望将这两个字符串连接成单个字符串r。要做到这一点,我们也可以借助常用的库函数strcpy和strcat。下面的方法似乎一目了然,可以却不能满足我们的目标:
char *r; strcpy(r,s); strcat(r,t );
之所以不行的原因在于不能确定r所向何处。我们应该还能看到,不仅要让r指向一个地址,而且r所指向的地址处应该有内存空间可供容纳字符串,这个内存空间应该是以某种方式已经被分配了的。
我们再试一次,记信给r分配一定的内存空间。
char r[100]; strchy(r,s); strcat(r,t);
只要s和t指向的字符串并不是太大,那么现在我们所用的方法就能够正常工作,不幸的是,C语言强制要求我们必须声明数组大小为一个常量,因此我们不能确保r足够大。然而,大多数C语言实现为我们提供了一个库函数malloc,该函数接受一个整数,然后分配能够容纳同样数目的字符的一块内存。大多数C语言实现还提供了一个库函数strlen,该函数返回一个字符串中所包括的字符数。有了这两个库函数,似乎我们就能够像下面这样操作了:
char *r, *malloc(); r = malloc(strlen(s)+strlen(t)); strcpy(r,s); strcat(r,t);
这个例子还是错的,原因归纳起来有三个。第一个原因,malloc函数有可能无法提供请求的内存,这种情况下malloc函数会通过返回一个空指针来作为“内存分配失败”事件的信号。
第二个原因,给r分配的内存是在使用之后应该及时释放,这一点务必要记信。因为前面的程序例子中r是作为一个局部变量声明的,因此当离开的r作用哉时,r自动被释放了。修订后的程序显式地释放内存。
第三个原因,也是最重要的原因,就是前面的全程在调用malloc函数时并示分配足够的内存。我们再回忆一下字符串以空字符作为结束标志的惯例。库函数strlen返回参数中字符串所包括的字符数目,而作为结束标志的空字符并未计算在内。因此,如果strlen(s)的值是n,那么字符串实际需要n+1个字符空间。所以,我们必须为r多分配一个字符的空间。做到了这些,并且注意了函数malloc是否调用成功,我们就得到正确的结果:
char *r, *malloc(); r = malloc(strlen(s)+strlen(t)+1); if(!r){ complain(); exit(1); } strcpy(r, s); strcat(r, t); /* 一段时间之后再使用 */ free(r);
未经允许不得转载:TacuLee » C陷阱与缺陷之非数组指针