在這里不記錄模塊功能劃分等問題老翘,假定函數(shù)接口功能已有明確的定義锈嫩。這樣的話就把討論局限在了函數(shù)名,傳入导梆,傳出參數(shù)的設(shè)計(jì)上了滓彰。
傳出參數(shù)(不一定指返回值)
- 通常情況下控妻,返回值都是int類型的數(shù)據(jù),返回0代表函數(shù)執(zhí)行成功揭绑,負(fù)數(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è)計(jì)成這樣
//返回值該不該,能不能釋放睡榆?很難從接口看出來
int get_fan_info(struct fan *fan,int id)
{
fan->xx = xx;
...
return SUCCESS;
}
void fan_list()
{
int i;
struct fan fan; //參數(shù)在椘妓粒空間上
for(i=0;i<MAX;i++){
get_fan_info(&fan,i);
printf(...about fan..);
}
get_fan_info(&fan,1) ;//只是單純的調(diào)一下這個函數(shù),會不會內(nèi)存泄漏胀屿?塘揣?
}
上面的實(shí)現(xiàn),其實(shí)很好的貫徹了 誰申請宿崭,誰釋放的標(biāo)準(zhǔn)亲铡。
- 有些情況下,返回值為指針效果很好
struct student *student_new(int id,const char *name); //從函數(shù)名便可以看出,此返回值為malloc出來的奖蔓。
//另外一些明確知道返回的指針?biāo)玫淖兞吭薏荩芷谳^長的。
struct student *student_find_by_name(const char *name);//從內(nèi)存查找一個student.
//此類接口有風(fēng)險锭硼,需要程序員明確內(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); //此時會段錯誤
}
其實(shí)上面代碼主要問題是破壞了誰申請誰釋放的原則搭独。
- 傳入?yún)?shù)的順序要有一定的邏輯性
//注意都是dest在錢,src在后
void* memcpy(void *desc,const void *src,size_t n);
char *strcpy(char *desc,const char *src);
//思考此時為什么返回值設(shè)計(jì)為指針類型廊镜?牙肝?
//第一個參數(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);