c语言函数接口设计的一些问题

在这里不记录模块功能划分等问题,假定函数接口功能已有明确的定义。这样的话就把讨论局限在了函数名,传入,传出参数的设计上了。

传出参数(不一定指返回值)

  1. 通常情况下,返回值都是int类型的数据,返回0代表函数执行成功,负数代表失败。
#define         SUCCESS                      0
#define         TIMEOUT                      1
#define         PARAM_VALID                  2

int do_something()
{
        if()
            return TIMEOUT;
       if()
           return  PARAM_VALID;
      return SUCCESS;
}
  1. 返回值尽量不要是指针类型
//返回值该不该,能不能释放?很难从接口看出来
struct fan  *get_fan_info(int id)
{
    static struct fan  fan;
     fan.xx = xx;
     ....
     return &fan    //此时不用释放返回值,函数不可重入

    struct fan *fan = malloc(sizeof(*fan));
    fan->xx = xx;
    ....
    return fan  //需要释放返回值,函数可重入。
}

void fan_list()
{
    int i;
    struct fan *f;
    for(i=0;i

此时我们可以把接口设计成这样

//返回值该不该,能不能释放?很难从接口看出来
int get_fan_info(struct fan *fan,int id) 
{
    fan->xx = xx;
    ...
   return SUCCESS;
}

void fan_list()
{
    int i;
    struct fan fan;  //参数在栈空间上
    for(i=0;i

上面的实现,其实很好的贯彻了 谁申请,谁释放的标准。

  1. 有些情况下,返回值为指针效果很好
struct student *student_new(int id,const char *name);  //从函数名便可以看出,此返回值为malloc出来的。

//另外一些明确知道返回的指针所引用的变量,生命周期较长的。
struct student *student_find_by_name(const char *name);//从内存查找一个student.
//此类接口有风险,需要程序员明确内存关系,最好有良好的注释。
  1. 返回值不应该为结构体。这里就不做具体讨论了。

传入参数

在函数内部最好不要破坏传入参数的内存结构,传入参数的排列顺序最好要有逻辑性。

  1. 不要破坏传入参数的内存结构
int send_request(const char *method,cJSON *param)
{
        ....
        free(param);
}

int do_something()
{
     cJSON *param = cJSON_CreateObject();
     cJSON_AddNumberToObject(param,"speed",123);
     send_request("set_fan_speed",param);
     cJSON_Delete(param);    //此时会段错误
}

其实上面代码主要问题是破坏了谁申请谁释放的原则。

  1. 传入参数的顺序要有一定的逻辑性
//注意都是dest在钱,src在后
void* memcpy(void *desc,const void  *src,size_t n);
char *strcpy(char *desc,const char *src);
//思考此时为什么返回值设计为指针类型??
//第一个参数为struct student *
int student_set_id(struct student *s,int id);
int student_set_name(struct student *s,const char *name);
  1. 传入参数的变量名,一定要表意清晰,尽量不用缩写,内部变量可使用缩写。
int student_set_name_by_id(struct student *student,const char *name)
{
       struct student *s = student_find_by_name(name); //内部采用缩写,参数不用缩写。
       if
          ...
      return SUCCESS;
}

函数名

函数名要表意清晰,遵守命名规范。几个典型示例如下:

struct student *student_new();
void student_destroy(struct student *student);

struct student *student_find_by_id(int id);
struct student *student_find_by_name(const char *name);

你可能感兴趣的:(c语言函数接口设计的一些问题)