小结下自己对C语言的指针使用的理解。
1,调用函数实现指针的申请与释放。
在开发中需要重复使用某个指针类型,为此专门写了一组处理该类型的函数,最基础就是该指针类型的申请与释放。常见的错误是通过传入一个一级指针来实现指针的申请或释放。
测试用的数据类型
typedef struct _MyStruct MyStruct;
typedef struct _FileInfo FileInfo;
struct _MyStruct
{
int m_nCount;
FileInfo * m_pFileInfo;
char m_cHttpUrlParam[128];
};
struct _FileInfo
{
char * m_pFilePath;
char * m_pFileName;
char * m_pReportTime;
int m_nSize;
};
MyStruct *pMyStruct;
测试函数_1
void create_MyStruct_1(MyStruct* pMyStruct)
{
pMyStruct = (MyStruct* )malloc( sizeof(MyStruct) );
}
MyStruct* create_MyStruct_2( void )
{
MyStruct* pMyStruct = NULL;
pMyStruct = (MyStruct*)malloc( sizeof(MyStruct) );
return pMyStruct;
}
void create_MyStruct_3( MyStruct** ppMyStruct )
{
*pp = (MyStruct*)malloc( sizeof(MyStruct) );
}
<span style="font-family:Arial;background-color: rgb(255, 255, 255);"></span>
测试代码
void main()
{
MyStruct* pMyStruct1, pMyStruct2, pMyStruct3;
create_MyStruct_1( pMyStruct1 );
pMyStruct2 = create_MyStruct_2();
create_MyStruct_1( &pMyStruct3 );
}
通过调用函数create_MyStruct_1是不能为pMyStruct1分配到内存的,还是老话题“函数调用是单向传递的值传递”,可参考谭浩强老师的《C语言程序设计》中举的例子,如下:
void swap(int x, int y)
{
int temp;
temp = x;
x = y;
y = temp;
}
试图通过调用swap(a,b)交换a和b的值是不能成功的,具体解释可以参考《C语言程序设计》关于“指针变量作为函数”一节相关内容。这个例子中,函数的形参是int类型,用类比的方法不难理解对于形参是指针类型的函数调用也是如此。对函数create_MyStruct_1稍做修改,这里记为create_MyStruct_4;
void create_MyStruct_4(MyStruct* pMS)
{
pMS = (MyStruct* )malloc( sizeof(MyStruct) );
}
在main()函数中调用create_MyStruct_1( pMyStruct1 ),的确为形参pMS动态分配了空间,pMS指向了新分配空间的首地址(若malloc分配成功),但是这个形参的值不能反向传递给pMyStruct1,而且还有个问题----在函数调用结束后,为pMS分配的空间没有得到释放。
为了能通过函数调用成功地为指针变量分配内存,可以通过函数返回值或者传递二级指针的方法实现,当然了也可以使用全局静态变量(一般不采用),分别参考函数create_MyStruct_2和create_MyStruct_3.
同样的道理,释放指针时 通过调用下面的函数destory(pString)也不能够正确地释放相应的指针pString
<pre class="cpp" name="code"><pre class="cpp" name="code">void destory( char* pStr )
{
if( !pStr )
{
free( pStr );
pStr = 0;
}
}
可以通过传递二级指针的方法来实现,如下:
void destory_2( char** ppStr )
{
if( *ppStr )
{
free( *ppStr );
*ppStr = 0;
}
}
调用destory_2(&pString)释放pString指针。当然了,也可以使用预定义实现,如下:
#define FREEIF(p) if(p){free((void*)(p));(p) = 0;}
释放指针时,调用
FREEIF(pString);
2,指向包含指针类型成员变量的结构体的指针的释放
小标题的表达太长了,解释下,这里讨论释放指向结构体的指针变量,该结构体的成员变量中也包含指针类型。
在main函数中想要通过函数调用释放pMyStruct,按照上面一小节的讨论,函数如下:
void destory_MyStruct( MyStruct **ppMyStruct)
{
if( !ppMyStruct || !(*ppMyStruct) )
{
return;
}
if( (*ppMyStruct)->m_pFileInfo )
{
destory_FileInfo( (FileInfo **)&(*ppMyStruct)->m_pFileInfo );
}
if( *ppMyStruct )
{
free( *ppMyStruct );
*ppMyStruct = 0;
}
}
void destory_FileInfo(FileInfo **ppFileInfo)
{
if( !ppFileInfo || !(*ppFileInfo))
{
return;
}
if( (*ppFileInfo)->m_pFileName )
{
free( (*ppFileInfo)->m_pFileName );
(*ppFileInfo)->m_pFileName = 0;
}
if( (*ppFileInfo)->m_pFilePath )
{
free((*ppFileInfo)->m_pFilePath);
(*ppFileInfo)->m_pFilePath = 0;
}
if((*ppFileInfo)->m_pReportTime)
{
free((*ppFileInfo)->m_pReportTime);
(*ppFileInfo)->m_pReportTime = 0;
}
if( *ppFileInfo )
{
free(*ppFileInfo);
*ppFileInfo = 0;
}
}
当然了,也可以借助上面的宏如下来写:
void destory_FileInfo(FileInfo **ppFileInfo)
{
if( !ppFileInfo || !(*ppFileInfo))
{
<pre class="cpp" name="code"> return;
}
FREEIF( (*ppFileInfo)->m_pFileName );
FREEIF( (*ppFileInfo)->m_pFilePath );
FREEIF( (*ppFileInfo)->m_pReportTime );
FREEIF( *ppFileInfo );
}
<pre class="cpp" name="code">void destory_MyStruct( MyStruct **ppMyStruct)
{
if( !ppMyStruct || !(*ppMyStruct) )
{
return;
}
if( (*ppMyStruct)->m_pFileInfo )<pre class="cpp" name="code"> {
destory_FileInfo( (FileInfo **)&(*ppMyStruct)->m_pFileInfo );
}
FREEIF( *ppMyStruct );
}
3,指针数组的指针分配与释放
可以认为指针数组的元素具有两个属性:数组元素的属性和指针类型的属性。在定义和引用的时候作为一般的数组元素来操作;在使用的时候遵照指针类型的特点。下面是个简单的例子:
void main()
{
int* pMyPA[10] = {0};
int i;
<em><span style="color:#3333ff;">//malloc </span></em>
for(i=0;i<10;i++)
{
pMyPA[i] = (int*)malloc(sizeof(int));
if( !pMyPA[i] )
{
return;
}
pMyPA[i] = &i;
}
<span style="color:#3366ff;"><em>//printf</em> </span>
for( i=0;i<10;i++ )
{
printf( "pMyPA[%d] = %d\n", i, *pMyPA[i] );
}
<span style="color:#3366ff;"><em>//free</em></span>
for( i=0;i<10;i++ )
{
<em><span style="color:#3366ff;">//使用前面的宏</span></em>
FREEIF(pMyPA[i]);
}
}