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. 返回指向已分配內存的指針

/* ret_ptr.h */
#ifndef RET_PTR_H
#define RET_PTR_H

extern char *get_a_day(int idx);

#endif
/* ret_ptr.c */
#include <string.h>
#include "ret_ptr.h"

static const char *msg[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
			"Thursday", "Friday", "Saturday"};

char *get_a_day(int idx)
{
     static char buf[20];
     strcpy(buf, msg[idx]);
     return buf;
}
/* main.c */
#include <stdio.h>
#include "ret_ptr.h"

int main(void)
{
     printf("%s %s\n", get_a_day(0), get_a_day(1));
     return 0;
}

這個程序的運行結果是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. 動態分配內存並返回指針

/* ret_allocator.h */
#ifndef RET_ALLOCATOR_H
#define RET_ALLOCATOR_H

typedef struct {
     int number;
     char *msg;
} unit_t;

extern unit_t *alloc_unit(void);
extern void free_unit(unit_t *);

#endif
/* ret_allocator.c */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "ret_allocator.h"

unit_t *alloc_unit(void)
{
     unit_t *p = malloc(sizeof(unit_t));
     if(p == NULL) {
	  printf("out of memory\n");
	  exit(1);
     }
     p->number = 3;
     p->msg = malloc(20);
     strcpy(p->msg, "Hello world!");
     return p;
}

void free_unit(unit_t *p)
{
     free(p->msg);
     free(p);
}
/* main.c */
#include <stdio.h>
#include "ret_allocator.h"

int main(void)
{
     unit_t *p = alloc_unit();

     printf("number: %d\nmsg: %s\n", p->number, p->msg);
     free_unit(p);
     p = NULL;
     return 0;
}

思考一下,通過參數分配內存需要兩層的指針,而通過返回值分配內存就只需要返回一層的指針,為什麼?