4. 返回值是指针的情况

返回值显然是传出的而不是传入的,如果返回值传出的是指针,和上一节通过参数传出指针类似,也分为两种情况:第一种是传出指向静态内存或已分配的动态内存的指针,例如localtime(3)inet_ntoa(3),第二种是在函数中动态分配内存并传出指向这块内存的指针,例如malloc(3),这种情况通常还要实现一个释放内存的函数,所以有和malloc(3)对应的free(3)。由于这两种情况的函数接口相同,应该在文档中说明是哪一种情况。

表 24.5. 返回指向已分配内存的指针示例:unit_t *func(void);

调用者实现者
  1. 调用函数

  2. 将返回值保存下来以备后用

  1. 规定返回值指针的类型unit_t *

  2. 返回一个指针

以下是一个完整的例子。

例 24.5. 返回指向已分配内存的指针

  1. /* ret_ptr.h */
  2. #ifndef RET_PTR_H
  3. #define RET_PTR_H
  4.  
  5. extern char *get_a_day(int idx);
  6.  
  7. #endif
  1. /* ret_ptr.c */
  2. #include <string.h>
  3. #include "ret_ptr.h"
  4.  
  5. static const char *msg[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
  6. "Thursday", "Friday", "Saturday"};
  7.  
  8. char *get_a_day(int idx)
  9. {
  10. static char buf[20];
  11. strcpy(buf, msg[idx]);
  12. return buf;
  13. }
  1. /* main.c */
  2. #include <stdio.h>
  3. #include "ret_ptr.h"
  4.  
  5. int main(void)
  6. {
  7. printf("%s %s\n", get_a_day(0), get_a_day(1));
  8. return 0;
  9. }

这个程序的运行结果是Sunday Monday吗?请读者自己分析一下。

表 24.6. 动态分配内存并返回指针示例:unit_t *alloc_unit(void); void free_unit(unit_t *p);

调用者实现者
  1. 调用alloc_unit分配内存

  2. 将返回值保存下来以备后用

  3. 调用free_unit释放内存

  1. 规定返回值指针的类型unit_t *

  2. alloc_unit分配内存并返回指向该内存的指针

  3. free_unit释放由alloc_unit分配的内存

以下是一个完整的例子。

例 24.6. 动态分配内存并返回指针

  1. /* ret_allocator.h */
  2. #ifndef RET_ALLOCATOR_H
  3. #define RET_ALLOCATOR_H
  4.  
  5. typedef struct {
  6. int number;
  7. char *msg;
  8. } unit_t;
  9.  
  10. extern unit_t *alloc_unit(void);
  11. extern void free_unit(unit_t *);
  12.  
  13. #endif
  1. /* ret_allocator.c */
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. #include "ret_allocator.h"
  6.  
  7. unit_t *alloc_unit(void)
  8. {
  9. unit_t *p = malloc(sizeof(unit_t));
  10. if(p == NULL) {
  11. printf("out of memory\n");
  12. exit(1);
  13. }
  14. p->number = 3;
  15. p->msg = malloc(20);
  16. strcpy(p->msg, "Hello world!");
  17. return p;
  18. }
  19.  
  20. void free_unit(unit_t *p)
  21. {
  22. free(p->msg);
  23. free(p);
  24. }
  1. /* main.c */
  2. #include <stdio.h>
  3. #include "ret_allocator.h"
  4.  
  5. int main(void)
  6. {
  7. unit_t *p = alloc_unit();
  8.  
  9. printf("number: %d\nmsg: %s\n", p->number, p->msg);
  10. free_unit(p);
  11. p = NULL;
  12. return 0;
  13. }

思考一下,通过参数分配内存需要两层的指针,而通过返回值分配内存就只需要返回一层的指针,为什么?