C:返回值为指针的函数解读
一、先看看下面的小程序:
[cpp] #include <stdio.h>
#include <stdlib.h>
typedef struct _STSTAFFINFO
{
char *pName; /*姓名*/
int iId; /*ID*/
}stStaffInfo;
/*根据ID获取姓名*/
char* GetStaffNameById(int iId)
{
int i;
stStaffInfo stTmpInfo[] =
{
{"Socrates", 1},
{"dyx1024", 2},
{"Kevin", 3},
{"Jim", 4}
};
for (i = 0; i < sizeof(stTmpInfo) / sizeof(stTmpInfo[0]); i++)
{
if (stTmpInfo[i].iId == iId)
{
return stTmpInfo[i].pName;
}
}
return "No match Name";
}
int main(int argc, char *argv[])
{
int iId = 2;
char *pName = GetStaffNameById(iId);
printf("Staff Name is : %s(id = %d)/n", pName, iId);
system("PAUSE");
return 0;
}
#include <stdio.h>
#include <stdlib.h>
typedef struct _STSTAFFINFO
{
char *pName; /*姓名*/
int iId; /*ID*/
}stStaffInfo;
/*根据ID获取姓名*/
char* GetStaffNameById(int iId)
{
int i;
stStaffInfo stTmpInfo[] =
{
{"Socrates", 1},
{"dyx1024", 2},
{"Kevin", 3},
{"Jim", 4}
};
for (i = 0; i < sizeof(stTmpInfo) / sizeof(stTmpInfo[0]); i++)
{
if (stTmpInfo[i].iId == iId)
{
return stTmpInfo[i].pName;
}
}
return "No match Name";
}
int main(int argc, char *argv[])
{
int iId = 2;
char *pName = GetStaffNameById(iId);
printf("Staff Name is : %s(id = %d)/n", pName, iId);
system("PAUSE");
return 0;
}
运行结果:
[plain]
Staff Name is : dyx1024(id = 2)
请按任意键继续. . .
Staff Name is : dyx1024(id = 2)
请按任意键继续. . .
运行结果与预期相符,但此程序却是一个有问题的程序,stTmpInfo是一个定义在函数GetStaffNameById中的临时变量,调用完此程序,它即被销毁,所以main函数中,pName所指对象的值是不确定的,在没被覆盖前,正确( 像此程序),但若被其他的函数调用覆盖,谁也不知道其值是什么。
二、如何改进?
方法有以下四种,推荐使用方法三。
1、将stTmpInfo定义为全局变量,如下
[cpp]
#include <stdio.h>
#include <stdlib.h>
typedef struct _STSTAFFINFO
{
char *pName; /*姓名*/
int iId; /*ID*/
}stStaffInfo;
static stStaffInfo stTmpInfo[] =
{
{"Socrates", 1},
{"dyx1024", 2},
{"Kevin", 3},
{"Jim", 4}
};
/*根据ID获取姓名*/
char* GetStaffNameById(int iId)
{
int i;
for (i = 0; i < sizeof(stTmpInfo) / sizeof(stTmpInfo[0]); i++)
{
if (stTmpInfo[i].iId == iId)
{
return stTmpInfo[i].pName;
}
}
return "No match Name";
}
int main(int argc, char *argv[])
{
int iId = 2;
char *pName = GetStaffNameById(iId);
printf("Staff Name is : %s(id = %d)/n", pName, iId);
system("PAUSE");<span style="white-space:pre"> </span>
return 0;
}
#include <stdio.h>
#include <stdlib.h>
typedef struct _STSTAFFINFO
{
char *pName; /*姓名*/
int iId; /*ID*/
}stStaffInfo;
static stStaffInfo stTmpInfo[] =
{
{"Socrates", 1},
{"dyx1024", 2},
{"Kevin", 3},
{"Jim", 4}
};
/*根据ID获取姓名*/
char* GetStaffNameById(int iId)
{
int i;
for (i = 0; i < sizeof(stTmpInfo) / sizeof(stTmpInfo[0]); i++)
{
if (stTmpInfo[i].iId == iId)
{
return stTmpInfo[i].pName;
}
}
return "No match Name";
}
int main(int argc, char *argv[])
{
int iId = 2;
char *pName = GetStaffNameById(iId);
printf("Staff Name is : %s(id = %d)/n", pName, iId);
system("PAUSE");<span style="white-space:pre"> </span>
return 0;
}
2、程序内部将stTmpInfo定义为static,如下:
[cpp]
#include <stdio.h>
#include <stdlib.h>
typedef struct _STSTAFFINFO
{
char *pName;
int iId; /*ID*/
}stStaffInfo;
char* GetStaffNameById(int iId)
{
int i;
static stStaffInfo stTmpInfo[] =
{
{"Socrates", 1},
{"dyx1024", 2},
{"Kevin", 3},
{"Jim", 4}
};
for (i = 0; i < sizeof(stTmpInfo) / sizeof(stTmpInfo[0]); i++)
{
if (stTmpInfo[i].iId == iId)
{
return stTmpInfo[i].pName;
}
}
return "No match Name";
}
int main(int argc, char *argv[])
{
int iId = 2;
char *pName = GetStaffNameById(iId);
printf("Staff Name is : %s(id = %d)/n", pName, iId);
system("PAUSE");
return 0;
}
#include <stdio.h>
#include <stdlib.h>
typedef struct _STSTAFFINFO
{
char *pName;
int iId; /*ID*/
}stStaffInfo;
char* GetStaffNameById(int iId)
{
int i;
static stStaffInfo stTmpInfo[] =
{
{"Socrates", 1},
{"dyx1024", 2},
{"Kevin", 3},
{"Jim", 4}
};
for (i = 0; i < sizeof(stTmpInfo) / sizeof(stTmpInfo[0]); i++)
{
if (stTmpInfo[i].iId == iId)
{
return stTmpInfo[i].pName;
}
}
return "No match Name";
}
int main(int argc, char *argv[])
{
int iId = 2;
char *pName = GetStaffNameById(iId);
printf("Staff Name is : %s(id = %d)/n", pName, iId);
system("PAUSE");
return 0;
}
3、修改接口,通过出参取回。
[cpp]
#include <stdio.h>
#include <stdlib.h>
typedef struct _STSTAFFINFO
{
char *pName;
int iId;
}stStaffInfo;
void GetStaffNameById(int iId, int iNameLen, char *pOutName)
{
int i;
stStaffInfo stTmpInfo[] =
{
{"Socrates", 1},
{"dyx1024", 2},
{"Kevin", 3},
{"Jim", 4}
};
if (NULL == pOutName)
{
return;
}
for (i = 0; i < sizeof(stTmpInfo) / sizeof(stTmpInfo[0]); i++)
{
if (stTmpInfo[i].iId == iId)
{
strncpy(pOutName, stTmpInfo[i].pName, iNameLen);
return;
}
}
strncpy(pOutName, "No match Name", iNameLen);
return;
}
int main(int argc, char *argv[])
{
int iId = 20;
char szName[21] = "/0";
GetStaffNameById(iId, 20, szName);
printf("Staff Name is : %s(id = %d)/n", szName, iId);
system("PAUSE");
return 0;
}
#include <stdio.h>
#include <stdlib.h>
typedef struct _STSTAFFINFO
{
char *pName;
int iId;
}stStaffInfo;
void GetStaffNameById(int iId, int iNameLen, char *pOutName)
{
int i;
stStaffInfo stTmpInfo[] =
{
{"Socrates", 1},
{"dyx1024", 2},
{"Kevin", 3},
{"Jim", 4}
};
if (NULL == pOutName)
{
return;
}
for (i = 0; i < sizeof(stTmpInfo) / sizeof(stTmpInfo[0]); i++)
{
if (stTmpInfo[i].iId == iId)
{
strncpy(pOutName, stTmpInfo[i].pName, iNameLen);
return;
}
}
strncpy(pOutName, "No match Name", iNameLen);
return;
}
int main(int argc, char *argv[])
{
int iId = 20;
char szName[21] = "/0";
GetStaffNameById(iId, 20, szName);
printf("Staff Name is : %s(id = %d)/n", szName, iId);
system("PAUSE");
return 0;
}
4、通过子程序分配内存,调用者释放解决。
[cpp]
#include <stdio.h>
#include <stdlib.h>
typedef struct _STSTAFFINFO
{
char *pName; /*ÐÕÃû*/
int iId; /*ID*/
}stStaffInfo;
/*¸ù¾ÝID»ñÈ¡ÐÕÃû*/
char* GetStaffNameById(int iId)
{
int i;
int iMaxNameLen = 20;
stStaffInfo stTmpInfo[] =
{
{"Socrates", 1},
{"dyx1024", 2},
{"Kevin", 3},
{"Jim", 4}
};
char *pRetName = (char *)malloc(iMaxNameLen);
if (NULL == pRetName)
{
exit(1);
}
for (i = 0; i < sizeof(stTmpInfo) / sizeof(stTmpInfo[0]); i++)
{
if (stTmpInfo[i].iId == iId)
{
strncpy(pRetName, stTmpInfo[i].pName, iMaxNameLen);
return pRetName;
}
}
strncpy(pRetName, "No match Name", iMaxNameLen);
return pRetName;
}
int main(int argc, char *argv[])
{
int iId = 2;
char *pName = GetStaffNameById(iId);
printf("Staff Name is : %s(id = %d)/n", pName, iId);
free(pName);
pName = NULL;
system("PAUSE");
return 0;
}
#include <stdio.h>
#include <stdlib.h>
typedef struct _STSTAFFINFO
{
char *pName; /*ÐÕÃû*/
int iId; /*ID*/
}stStaffInfo;
/*¸ù¾ÝID»ñÈ¡ÐÕÃû*/
char* GetStaffNameById(int iId)
{
int i;
int iMaxNameLen = 20;
stStaffInfo stTmpInfo[] =
{
{"Socrates", 1},
{"dyx1024", 2},
{"Kevin", 3},
{"Jim", 4}
};
char *pRetName = (char *)malloc(iMaxNameLen);
if (NULL == pRetName)
{
exit(1);
}
for (i = 0; i < sizeof(stTmpInfo) / sizeof(stTmpInfo[0]); i++)
{
if (stTmpInfo[i].iId == iId)
{
strncpy(pRetName, stTmpInfo[i].pName, iMaxNameLen);
return pRetName;
}
}
strncpy(pRetName, "No match Name", iMaxNameLen);
return pRetName;
}
int main(int argc, char *argv[])
{
int iId = 2;
char *pName = GetStaffNameById(iId);
printf("Staff Name is : %s(id = %d)/n", pName, iId);
free(pName);
pName = NULL;
system("PAUSE");
return 0;
}
摘自 Socrates的专栏