函数返回指针
函数可以返回指针,让调用者访问函数内部创建的数据。但返回局部变量的地址是致命错误——函数返回后栈帧销毁,该地址变为无效。安全的返回方式包括:返回静态变量地址、返回动态分配内存的地址、或返回传入参数的地址。
危险:返回局部变量
int *bad_func(void)
{
int local = 10; /* 局部变量,栈上 */
return &local; /* 危险!函数返回后 local 销毁 */
}
int *p = bad_func();
printf("%d\n", *p); /* 未定义行为:悬垂指针 */
安全方式 1:静态变量
int *get_counter(void)
{
static int count = 0; /* 静态存储期 */
count++;
return &count; /* 安全 */
}
注意:静态变量在多次调用间共享,不是线程安全的。
安全方式 2:动态分配
int *create_array(int n)
{
int *arr = malloc(n * sizeof(int));
if (arr != NULL) {
for (int i = 0; i < n; i++)
arr[i] = i;
}
return arr; /* 调用者负责 free */
}
int *arr = create_array(10);
/* 使用 arr */
free(arr); /* 释放 */
安全方式 3:返回传入参数
char *trim(char *str)
{
/* 修改并返回 str */
char *start = str;
while (isspace(*start)) start++;
char *end = start + strlen(start) - 1;
while (end > start && isspace(*end)) end--;
*(end + 1) = '\0';
return start; /* 返回传入的指针 */
}
返回字符串
/* 错误:返回局部数组 */
char *get_string_bad(void)
{
char str[] = "Hello";
return str; /* 危险! */
}
/* 正确 1:静态 */
char *get_string_static(void)
{
static char str[] = "Hello";
return str;
}
/* 正确 2:字符串字面量 */
char *get_string_literal(void)
{
return "Hello"; /* 字符串字面量有静态存储期 */
}
/* 正确 3:动态分配 */
char *get_string_dynamic(const char *src)
{
char *str = malloc(strlen(src) + 1);
if (str != NULL)
strcpy(str, src);
return str;
}
常见错误
返回局部变量地址:
int *func(void)
{
int x = 10;
return &x; /* 错误! */
}
忘记释放动态内存:
int *p = create_array(100);
/* 使用 p */
/* 忘记 free(p) → 内存泄漏 */
最佳实践
- 绝不返回局部自动变量的地址
- 返回静态变量时,注意线程安全和多次调用共享问题
- 返回动态内存时,文档化调用者的释放责任
- 返回传入参数时,明确修改行为
- 考虑返回状态码,通过输出参数返回指针