非数组的指针
在C语言中,字符串常量代表了一块包括字符串中所有字符以及一个空字符('\0')的内存
区域的地址。因为C语言要求字符串常量以空字符作为结束标志,对于其他字符串,C程序员通常
也沿用了这一惯例。
字符串s和t,将两个字符串连接成单个字符串r。要做到这一点,我们可以借助常用的库函数strcpy
和strcat。下面的方法似乎一目了然,可是却不能满足我们的目标:
char *r;
strcpy(r, s);
strcat(r, t);
之所以不行,是因为不能确定r指向何处。我们还应该看到,不仅要让r指向一个地址,而且r所指向的地址还应该有内存空间可供容纳字符串,这个内存空间应该是以某种方式已经被分配了的。
给r分配一定的内存空间:
char r[100];
strcpy(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自动被释放了。修改后的程序显示地给r分配了内存。修订后的程序显示地给r分配了内存,为此就必须显示地释放内存。
第三个原因,也是最重要的原因,就是前面的例程在调用malloc函数时并未分配足够的内存。因为字符串以空字符作为结束符标志的惯例。库函数strlen返回参数中字符串所包含的字符数目,而作为结束标志的空字符并未计算在内。
因此,如果strlen(s)的值是n,那么字符串实际需要n+1个字符的空间。所以,我们必须为r多分配一个字符的空间。
char *r, *malloc();
r = malloc(strlen(s) + strlen(t) + 1);
if (!r) {
complain();
exit();
}
strcpy(r, s);
strcat(r, t);
/*一段时间后再使用*/
free(r);