結構體中指標賦值問題的分析及C程式碼示例
問題描述
某結構體的定義如下:
typedef struct
{
int iAge; // 年齡
char szAddr1[100]; // 地址1
char *pszAddr2; // 地址2
char **pszAddr3; // 地址3
} T_PeopleInfo;
請問如何對結構體中的各個成員變數(尤其是指標變數)進行賦值?
問題分析及C程式碼示例
我們可以看到,在結構體T_PeopleInfo中,pszAddr2和pszAddr3均為指標,其中pszAddr2為一級指標,pszAddr3為二級指標。本文的重點,就是要找到對一級指標和二級指標賦值的正確方法。
我們把結構體T_PeopleInfo放到具體的C程式碼中,以直觀地展現對結構體中的各個成員變數的賦值方法。
我們首先編寫如下程式(程式1):
/**********************************************************************
* 版權所有 (C)2016, Zhou Zhaoxiong。
*
* 檔名稱:PointerTest.c
* 檔案標識:無
* 內容摘要:演示指標的用法
* 其它說明:無
* 當前版本:V1.0
* 作 者:Zhou Zhaoxiong
* 完成日期:20160712
*
*************** *******************************************************/
#include <stdio.h>
// 重定義資料型別
typedef signed int INT32;
typedef unsigned int UINT32;
typedef unsigned char UINT8;
// 結構體定義
typedef struct
{
UINT32 iAge; // 年齡
UINT8 szAddr1[100]; // 地址1
UINT8 *pszAddr2; // 地址2
UINT8 **pszAddr3; // 地址3
} T_PeopleInfo;
/****************************************************************
* 功能描述: 主函式
* 輸入引數: 無
* 輸出引數: 無
* 返 回 值: 0-執行完成
* 其他說明: 無
* 修改日期 版本號 修改人 修改內容
* -------------------------------------------------------------
* 20160712 V1.0 Zhou Zhaoxiong 建立
****************************************************************/
INT32 main(void)
{
T_PeopleInfo tPeopleInfo = {0};
// 結構體變數賦值
// 對iAge賦值
tPeopleInfo.iAge = 10;
// 對szAddr1賦值
strncpy(tPeopleInfo.szAddr1, "Chongqing, China!", strlen("Chongqing, China!"));
// 對pszAddr2賦值
strncpy(tPeopleInfo.pszAddr2, "Chengdu, China!", strlen("Chengdu, China!"));
// 對pszAddr3賦值
strncpy(tPeopleInfo.pszAddr3, "Wuhan, China!", strlen("Wuhan, China!"));
// 列印變數的值
printf("Age=%d, Addr1=%s, Addr2=%s, Addr3=%s", tPeopleInfo.iAge, tPeopleInfo.szAddr1, tPeopleInfo.pszAddr2, tPeopleInfo.pszAddr3);
return 0;
}
在程式1中,我們按照對結構體中的陣列的賦值方法對指標賦值,程式可以編譯通過,但執行的時候,程式便會掛掉。究其原因,是因為沒有為pszAddr2和pszAddr3指標分配記憶體空間。
我們對程式1進行改進,編寫出以下程式(程式2):
/**********************************************************************
* 版權所有 (C)2016, Zhou Zhaoxiong。
*
* 檔名稱:PointerTest.c
* 檔案標識:無
* 內容摘要:演示指標的用法
* 其它說明:無
* 當前版本:V1.0
* 作 者:Zhou Zhaoxiong
* 完成日期:20160712
*
**********************************************************************/
#include <stdio.h>
// 重定義資料型別
typedef signed int INT32;
typedef unsigned int UINT32;
typedef signed char INT8;
// 結構體定義
typedef struct
{
UINT32 iAge; // 年齡
INT8 szAddr1[100]; // 地址1
INT8 *pszAddr2; // 地址2
INT8 **pszAddr3; // 地址3
} T_PeopleInfo;
/****************************************************************
* 功能描述: 主函式
* 輸入引數: 無
* 輸出引數: 無
* 返 回 值: 0-執行完成
* 其他說明: 無
* 修改日期 版本號 修改人 修改內容
* -------------------------------------------------------------
* 20160712 V1.0 Zhou Zhaoxiong 建立
****************************************************************/
INT32 main(void)
{
T_PeopleInfo tPeopleInfo = {0};
// 結構體變數賦值
// 對iAge賦值
tPeopleInfo.iAge = 10;
// 對szAddr1賦值
strncpy(tPeopleInfo.szAddr1, "Chongqing, China!", strlen("Chongqing, China!"));
// 對pszAddr2賦值
tPeopleInfo.pszAddr2 = (INT8 *)malloc(100);
if (tPeopleInfo.pszAddr2 == NULL)
{
return -1;
}
strncpy(tPeopleInfo.pszAddr2, "Chengdu, China!", strlen("Chengdu, China!"));
// 對pszAddr3賦值
tPeopleInfo.pszAddr3 = (INT8 *)malloc(100);
if (tPeopleInfo.pszAddr3 == NULL)
{
return -2;
}
strncpy(tPeopleInfo.pszAddr3, "Wuhan, China!", strlen("Wuhan, China!"));
// 列印變數的值
printf("Age=%d, Addr1=%s, Addr2=%s, Addr3=%s\n", tPeopleInfo.iAge, tPeopleInfo.szAddr1, tPeopleInfo.pszAddr2, tPeopleInfo.pszAddr3);
return 0;
}
在程式2中,我們先使用malloc為pszAddr2和pszAddr3分配了記憶體空間(注意,執行malloc之後,要判斷指標是否為空),此時就可以將變數值賦給它們。程式編譯和執行都是正常的,輸出結果如下:
~/zhouzx/Test/PointerTest> PointerTest
Age=10, Addr1=Chongqing, China!, Addr2=Chengdu, China!, Addr3=Wuhan, China!
除了程式2可以實現對一級指標和二級指標的正常賦值之外,我們還可以編寫如下程式(程式3):
/**********************************************************************
* 版權所有 (C)2016, Zhou Zhaoxiong。
*
* 檔名稱:PointerTest.c
* 檔案標識:無
* 內容摘要:演示指標的用法
* 其它說明:無
* 當前版本:V1.0
* 作 者:Zhou Zhaoxiong
* 完成日期:20160712
*
**********************************************************************/
#include <stdio.h>
// 重定義資料型別
typedef signed int INT32;
typedef unsigned int UINT32;
typedef signed char INT8;
// 結構體定義
typedef struct
{
UINT32 iAge; // 年齡
INT8 szAddr1[100]; // 地址1
INT8 *pszAddr2; // 地址2
INT8 **pszAddr3; // 地址3
} T_PeopleInfo;
/****************************************************************
* 功能描述: 主函式
* 輸入引數: 無
* 輸出引數: 無
* 返 回 值: 0-執行完成
* 其他說明: 無
* 修改日期 版本號 修改人 修改內容
* -------------------------------------------------------------
* 20160712 V1.0 Zhou Zhaoxiong 建立
****************************************************************/
INT32 main(void)
{
T_PeopleInfo tPeopleInfo = {0};
// 結構體變數賦值
// 對iAge賦值
tPeopleInfo.iAge = 10;
// 對szAddr1賦值
strncpy(tPeopleInfo.szAddr1, "Chongqing, China!", strlen("Chongqing, China!"));
// 對pszAddr2賦值
tPeopleInfo.pszAddr2 = "Chengdu, China!";
// 對pszAddr3賦值
tPeopleInfo.pszAddr3 = "Wuhan, China!";
// 列印變數的值
printf("Age=%d, Addr1=%s, Addr2=%s, Addr3=%s\n", tPeopleInfo.iAge, tPeopleInfo.szAddr1, tPeopleInfo.pszAddr2, tPeopleInfo.pszAddr3);
return 0;
}
在程式3中,我們直接將字串賦給了pszAddr2和pszAddr3,也就是將這兩個字串的首地址賦給了指標。那麼,指標所指向的地址中存放的內容就是字串的值。程式編譯和執行都是正常的,輸出結果如下:
~/zhouzx/Test/PointerTest> PointerTest
Age=10, Addr1=Chongqing, China!, Addr2=Chengdu, China!, Addr3=Wuhan, China!
另,對於二級指標的賦值,我們還可以編寫如下程式(程式4):
/**********************************************************************
* 版權所有 (C)2016, Zhou Zhaoxiong。
*
* 檔名稱:PointerTest.c
* 檔案標識:無
* 內容摘要:演示指標的用法
* 其它說明:無
* 當前版本:V1.0
* 作 者:Zhou Zhaoxiong
* 完成日期:20160712
*
**********************************************************************/
#include <stdio.h>
// 重定義資料型別
typedef signed int INT32;
typedef unsigned int UINT32;
typedef signed char INT8;
// 結構體定義
typedef struct
{
UINT32 iAge; // 年齡
INT8 szAddr1[100]; // 地址1
INT8 *pszAddr2; // 地址2
INT8 **pszAddr3; // 地址3
} T_PeopleInfo;
/****************************************************************
* 功能描述: 主函式
* 輸入引數: 無
* 輸出引數: 無
* 返 回 值: 0-執行完成
* 其他說明: 無
* 修改日期 版本號 修改人 修改內容
* -------------------------------------------------------------
* 20160712 V1.0 Zhou Zhaoxiong 建立
****************************************************************/
INT32 main(void)
{
T_PeopleInfo tPeopleInfo = {0};
// 結構體變數賦值
// 對iAge賦值
tPeopleInfo.iAge = 10;
// 對szAddr1賦值
strncpy(tPeopleInfo.szAddr1, "Chongqing, China!", strlen("Chongqing, China!"));
// 對pszAddr2賦值
tPeopleInfo.pszAddr2 = "Chengdu, China!";
// 對pszAddr3賦值
tPeopleInfo.pszAddr3 = (INT8 *)malloc(100);
if (tPeopleInfo.pszAddr3 == NULL)
{
return -1;
}
*(tPeopleInfo.pszAddr3) = "Wuhan, China!";
// 列印變數的值
printf("Age=%d, Addr1=%s, Addr2=%s, Addr3=%s\n", tPeopleInfo.iAge, tPeopleInfo.szAddr1, tPeopleInfo.pszAddr2, *(tPeopleInfo.pszAddr3));
return 0;
}
在程式4中,我們先用malloc為pszAddr3分配了記憶體空間,然後便可以使用該指標來接收字串變數的值(注意,這裡是將“Wuhan, China!”賦給了*(tPeopleInfo.pszAddr3))。程式編譯和執行都是正常的,輸出結果如下:
~/zhouzx/Test/PointerTest> PointerTest
Age=10, Addr1=Chongqing, China!, Addr2=Chengdu, China!, Addr3=Wuhan, China!
總結
本文對結構體中指標賦值問題進行了分析,並用C程式碼演示了指標的賦值方法。
在實際的C語言專案中,很多程式出現問題,就是對指標的處理不當造成的。因此,熟練掌握各種指標的使用方法,是對一個合格的軟體開發人員的基本要求。