在這里不記錄模塊功能劃分等問題,假定函數(shù)接口功能已有明確的定義。這樣的話就把討論局限在了函數(shù)名,傳入,傳出參數(shù)的設(shè)計上了。
傳出參數(shù)(不一定指返回值)
- 通常情況下,返回值都是int類型的數(shù)據(jù),返回0代表函數(shù)執(zhí)行成功,負數(shù)代表失敗。
#define SUCCESS 0
#define TIMEOUT 1
#define PARAM_VALID 2
int do_something()
{
if()
return TIMEOUT;
if()
return PARAM_VALID;
return SUCCESS;
}
- 返回值盡量不要是指針類型
//返回值該不該,能不能釋放?很難從接口看出來
struct fan *get_fan_info(int id)
{
static struct fan fan;
fan.xx = xx;
....
return &fan //此時不用釋放返回值,函數(shù)不可重入
struct fan *fan = malloc(sizeof(*fan));
fan->xx = xx;
....
return fan //需要釋放返回值,函數(shù)可重入。
}
void fan_list()
{
int i;
struct fan *f;
for(i=0;i<MAX;i++){
f = get_fan_info(i);
printf(...about fan..);
free(f) ; //到底要不要執(zhí)行這句。????
}
get_fan_info(i);// 只是單純的調(diào)一下這個函數(shù),可是會不會內(nèi)存泄漏???
}
此時我們可以把接口設(shè)計成這樣
//返回值該不該,能不能釋放?很難從接口看出來
int get_fan_info(struct fan *fan,int id)
{
fan->xx = xx;
...
return SUCCESS;
}
void fan_list()
{
int i;
struct fan fan; //參數(shù)在??臻g上
for(i=0;i<MAX;i++){
get_fan_info(&fan,i);
printf(...about fan..);
}
get_fan_info(&fan,1) ;//只是單純的調(diào)一下這個函數(shù),會不會內(nèi)存泄漏??
}
上面的實現(xiàn),其實很好的貫徹了 誰申請,誰釋放的標準。
- 有些情況下,返回值為指針效果很好
struct student *student_new(int id,const char *name); //從函數(shù)名便可以看出,此返回值為malloc出來的。
//另外一些明確知道返回的指針所引用的變量,生命周期較長的。
struct student *student_find_by_name(const char *name);//從內(nèi)存查找一個student.
//此類接口有風險,需要程序員明確內(nèi)存關(guān)系,最好有良好的注釋。
- 返回值不應(yīng)該為結(jié)構(gòu)體。這里就不做具體討論了。
傳入?yún)?shù)
在函數(shù)內(nèi)部最好不要破壞傳入?yún)?shù)的內(nèi)存結(jié)構(gòu),傳入?yún)?shù)的排列順序最好要有邏輯性。
- 不要破壞傳入?yún)?shù)的內(nèi)存結(jié)構(gòu)
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); //此時會段錯誤
}
其實上面代碼主要問題是破壞了誰申請誰釋放的原則。
- 傳入?yún)?shù)的順序要有一定的邏輯性
//注意都是dest在錢,src在后
void* memcpy(void *desc,const void *src,size_t n);
char *strcpy(char *desc,const char *src);
//思考此時為什么返回值設(shè)計為指針類型??
//第一個參數(shù)為struct student *
int student_set_id(struct student *s,int id);
int student_set_name(struct student *s,const char *name);
- 傳入?yún)?shù)的變量名,一定要表意清晰,盡量不用縮寫,內(nèi)部變量可使用縮寫。
int student_set_name_by_id(struct student *student,const char *name)
{
struct student *s = student_find_by_name(name); //內(nèi)部采用縮寫,參數(shù)不用縮寫。
if
...
return SUCCESS;
}
函數(shù)名
函數(shù)名要表意清晰,遵守命名規(guī)范。幾個典型示例如下:
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);