以下信息可能比您要查找的信息多得多。现在不要太担心吸收它,但你以后可能会需要它。
首先,关于术语的重要说明。C 没有“字符串”类型。引用 ISO C 标准:
字符串是由第一个空字符终止并包括第一个空字符的连续字符序列。[...]指向字符串的指针是指向其初始(最低地址)字符的指针。
特别是,一个char*
值是一个指针,而不是一个字符串(尽管我们通常使用char*
指针来访问和操作字符串)。即使一个数组本身也不是一个字符串,尽管它可以包含一个字符串。
对于您的(相对简单的)函数,char*
您返回的值指向字符串文字的(第一个字符),因此内存管理不是问题。对于更复杂的情况,该语言坦率地说并不是特别有用,您必须自己做一些工作来管理内存。
一个函数可以很容易地返回一个char*
指向字符串的值,允许调用者对这个字符串做它喜欢做的事情——但是组成这个字符串的字符存储在哪里呢?
有(至少)三种常见的方法。
(1) 函数返回一个指向静态数组开头的指针char
:
char *func(void) {
static char result[100];
// copy data into result
return result;
}
这可行,但它有一些缺点。该数组只有一个副本result
,连续调用func()
将破坏该数组的内容。并且数组有固定的大小;它必须足够大以容纳它可以返回的最大字符串。标准 Casctime()
函数以这种方式工作。
(2) 调用者可以传入一个指向字符串的指针,并让函数填充它:
void func(char *buffer) {
// code to copy data into the array pointed to by buffer
}
这给调用者带来了负担,它必须分配一个 的数组char
,特别是必须知道它需要多大。
(3) 该函数可以使用以下方法为字符串分配内存malloc()
:
char *func(void) {
char *result = malloc(some_number);
if (result == NULL) {
// allocation failed, cope with the error
}
// copy data into the array pointed to by result
return result;
}
这样做的好处是函数可以决定它需要分配多少内存。但是调用者必须知道字符串是在堆上分配的,所以它可以稍后通过调用来释放它free()
。malloc()
andfree()
函数也可能相对昂贵(但不要担心,除非您确定程序的性能不够好)。
其实还有第四种方法,但是错了:
char *bad_func(void) {
char result[100];
// copy data into result
return result; // equivalent to "return &result[0];"
}
这里的问题是它result
是函数本地的,并且没有定义为static
,所以一旦函数返回,数组对象就不再存在。调用者将收到一个指向不再保留的内存的指针,并且可以在你背后重复使用。您可以返回指向本地static
对象的指针(因为在程序的整个生命周期中都存在单个副本),您可以返回本地非对象的值static
,但不能安全地返回本地非对象的地址static
目的。
comp.lang.c FAQ是一个很好的资源。