結(jié)構(gòu)體中指針賦值問(wèn)題的分析及C代碼示例
問(wèn)題描述
某結(jié)構(gòu)體的定義如下:
- typedef struct
- {
- int iAge; // 年齡
- char szAddr1[100]; // 地址1
- char *pszAddr2; // 地址2
- char **pszAddr3; // 地址3
- } T_PeopleInfo;
請(qǐng)問(wèn)如何對(duì)結(jié)構(gòu)體中的各個(gè)成員變量(尤其是指針變量)進(jìn)行賦值?
問(wèn)題分析及C代碼示例
我們可以看到,在結(jié)構(gòu)體T_PeopleInfo中,pszAddr2和pszAddr3均為指針,其中pszAddr2為一級(jí)指針,pszAddr3為二級(jí)指針。本文的重點(diǎn),就是要找到對(duì)一級(jí)指針和二級(jí)指針賦值的正確方法。
我們把結(jié)構(gòu)體T_PeopleInfo放到具體的C代碼中,以直觀地展現(xiàn)對(duì)結(jié)構(gòu)體中的各個(gè)成員變量的賦值方法。
我們首先編寫(xiě)如下程序(程序1):
- /**********************************************************************
- * 版權(quán)所有 (C)2016, Zhou Zhaoxiong。
- *
- * 文件名稱:PointerTest.c
- * 文件標(biāo)識(shí):無(wú)
- * 內(nèi)容摘要:演示指針的用法
- * 其它說(shuō)明:無(wú)
- * 當(dāng)前版本:V1.0
- * 作 者:Zhou Zhaoxiong
- * 完成日期:20160712
- *
- **********************************************************************/
- #include <stdio.h>
- // 重定義數(shù)據(jù)類型
- typedef signed int INT32;
- typedef unsigned int UINT32;
- typedef unsigned char UINT8;
- // 結(jié)構(gòu)體定義
- typedef struct
- {
- UINT32 iAge; // 年齡
- UINT8 szAddr1[100]; // 地址1
- UINT8 *pszAddr2; // 地址2
- UINT8 **pszAddr3; // 地址3
- } T_PeopleInfo;
- /****************************************************************
- * 功能描述: 主函數(shù)
- * 輸入?yún)?shù): 無(wú)
- * 輸出參數(shù): 無(wú)
- * 返 回 值: 0-執(zhí)行完成
- * 其他說(shuō)明: 無(wú)
- * 修改日期 版本號(hào) 修改人 修改內(nèi)容
- * -------------------------------------------------------------
- * 20160712 V1.0 Zhou Zhaoxiong 創(chuàng)建
- ****************************************************************/
- INT32 main(void)
- {
- T_PeopleInfo tPeopleInfo = {0};
- // 結(jié)構(gòu)體變量賦值
- // 對(duì)iAge賦值
- tPeopleInfo.iAge = 10;
- // 對(duì)szAddr1賦值
- strncpy(tPeopleInfo.szAddr1, "Chongqing, China!", strlen("Chongqing, China!"));
- // 對(duì)pszAddr2賦值
- strncpy(tPeopleInfo.pszAddr2, "Chengdu, China!", strlen("Chengdu, China!"));
- // 對(duì)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中,我們按照對(duì)結(jié)構(gòu)體中的數(shù)組的賦值方法對(duì)指針賦值,程序可以編譯通過(guò),但運(yùn)行的時(shí)候,程序便會(huì)掛掉。究其原因,是因?yàn)闆](méi)有為pszAddr2和pszAddr3指針?lè)峙鋬?nèi)存空間。
我們對(duì)程序1進(jìn)行改進(jìn),編寫(xiě)出以下程序(程序2):
- /**********************************************************************
- * 版權(quán)所有 (C)2016, Zhou Zhaoxiong。
- *
- * 文件名稱:PointerTest.c
- * 文件標(biāo)識(shí):無(wú)
- * 內(nèi)容摘要:演示指針的用法
- * 其它說(shuō)明:無(wú)
- * 當(dāng)前版本:V1.0
- * 作 者:Zhou Zhaoxiong
- * 完成日期:20160712
- *
- **********************************************************************/
- #include <stdio.h>
- // 重定義數(shù)據(jù)類型
- typedef signed int INT32;
- typedef unsigned int UINT32;
- typedef signed char INT8;
- // 結(jié)構(gòu)體定義
- typedef struct
- {
- UINT32 iAge; // 年齡
- INT8 szAddr1[100]; // 地址1
- INT8 *pszAddr2; // 地址2
- INT8 **pszAddr3; // 地址3
- } T_PeopleInfo;
- /****************************************************************
- * 功能描述: 主函數(shù)
- * 輸入?yún)?shù): 無(wú)
- * 輸出參數(shù): 無(wú)
- * 返 回 值: 0-執(zhí)行完成
- * 其他說(shuō)明: 無(wú)
- * 修改日期 版本號(hào) 修改人 修改內(nèi)容
- * -------------------------------------------------------------
- * 20160712 V1.0 Zhou Zhaoxiong 創(chuàng)建
- ****************************************************************/
- INT32 main(void)
- {
- T_PeopleInfo tPeopleInfo = {0};
- // 結(jié)構(gòu)體變量賦值
- // 對(duì)iAge賦值
- tPeopleInfo.iAge = 10;
- // 對(duì)szAddr1賦值
- strncpy(tPeopleInfo.szAddr1, "Chongqing, China!", strlen("Chongqing, China!"));
- // 對(duì)pszAddr2賦值
- tPeopleInfo.pszAddr2 = (INT8 *)malloc(100);
- if (tPeopleInfo.pszAddr2 == NULL)
- {
- return -1;
- }
- strncpy(tPeopleInfo.pszAddr2, "Chengdu, China!", strlen("Chengdu, China!"));
- // 對(duì)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分配了內(nèi)存空間(注意,執(zhí)行malloc之后,要判斷指針是否為空),此時(shí)就可以將變量值賦給它們。程序編譯和運(yùn)行都是正常的,輸出結(jié)果如下:
- ~/zhouzx/Test/PointerTest> PointerTest
- Age=10, Addr1=Chongqing, China!, Addr2=Chengdu, China!, Addr3=Wuhan, China!
除了程序2可以實(shí)現(xiàn)對(duì)一級(jí)指針和二級(jí)指針的正常賦值之外,我們還可以編寫(xiě)如下程序(程序3):
- * 版權(quán)所有 (C)2016, Zhou Zhaoxiong。
- *
- * 文件名稱:PointerTest.c
- * 文件標(biāo)識(shí):無(wú)
- * 內(nèi)容摘要:演示指針的用法
- * 其它說(shuō)明:無(wú)
- * 當(dāng)前版本:V1.0
- * 作 者:Zhou Zhaoxiong
- * 完成日期:20160712
- *
- **********************************************************************/
- #include <stdio.h>
- // 重定義數(shù)據(jù)類型
- typedef signed int INT32;
- typedef unsigned int UINT32;
- typedef signed char INT8;
- // 結(jié)構(gòu)體定義
- typedef struct
- {
- UINT32 iAge; // 年齡
- INT8 szAddr1[100]; // 地址1
- INT8 *pszAddr2; // 地址2
- INT8 **pszAddr3; // 地址3
- } T_PeopleInfo;
- /****************************************************************
- * 功能描述: 主函數(shù)
- * 輸入?yún)?shù): 無(wú)
- * 輸出參數(shù): 無(wú)
- * 返 回 值: 0-執(zhí)行完成
- * 其他說(shuō)明: 無(wú)
- * 修改日期 版本號(hào) 修改人 修改內(nèi)容
- * -------------------------------------------------------------
- * 20160712 V1.0 Zhou Zhaoxiong 創(chuàng)建
- ****************************************************************/
- INT32 main(void)
- {
- T_PeopleInfo tPeopleInfo = {0};
- // 結(jié)構(gòu)體變量賦值
- // 對(duì)iAge賦值
- tPeopleInfo.iAge = 10;
- // 對(duì)szAddr1賦值
- strncpy(tPeopleInfo.szAddr1, "Chongqing, China!", strlen("Chongqing, China!"));
- // 對(duì)pszAddr2賦值
- tPeopleInfo.pszAddr2 = "Chengdu, China!";
- // 對(duì)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,也就是將這兩個(gè)字符串的首地址賦給了指針。那么,指針?biāo)赶虻牡刂分写娣诺膬?nèi)容就是字符串的值。程序編譯和運(yùn)行都是正常的,輸出結(jié)果如下:
- ~/zhouzx/Test/PointerTest> PointerTest
- Age=10, Addr1=Chongqing, China!, Addr2=Chengdu, China!, Addr3=Wuhan, China!
另,對(duì)于二級(jí)指針的賦值,我們還可以編寫(xiě)如下程序(程序4):
- /**********************************************************************
- * 版權(quán)所有 (C)2016, Zhou Zhaoxiong。
- *
- * 文件名稱:PointerTest.c
- * 文件標(biāo)識(shí):無(wú)
- * 內(nèi)容摘要:演示指針的用法
- * 其它說(shuō)明:無(wú)
- * 當(dāng)前版本:V1.0
- * 作 者:Zhou Zhaoxiong
- * 完成日期:20160712
- *
- **********************************************************************/
- #include <stdio.h>
- // 重定義數(shù)據(jù)類型
- typedef signed int INT32;
- typedef unsigned int UINT32;
- typedef signed char INT8;
- // 結(jié)構(gòu)體定義
- typedef struct
- {
- UINT32 iAge; // 年齡
- INT8 szAddr1[100]; // 地址1
- INT8 *pszAddr2; // 地址2
- INT8 **pszAddr3; // 地址3
- } T_PeopleInfo;
- /****************************************************************
- * 功能描述: 主函數(shù)
- * 輸入?yún)?shù): 無(wú)
- * 輸出參數(shù): 無(wú)
- * 返 回 值: 0-執(zhí)行完成
- * 其他說(shuō)明: 無(wú)
- * 修改日期 版本號(hào) 修改人 修改內(nèi)容
- * -------------------------------------------------------------
- * 20160712 V1.0 Zhou Zhaoxiong 創(chuàng)建
- ****************************************************************/
- INT32 main(void)
- {
- T_PeopleInfo tPeopleInfo = {0};
- // 結(jié)構(gòu)體變量賦值
- // 對(duì)iAge賦值
- tPeopleInfo.iAge = 10;
- // 對(duì)szAddr1賦值
- strncpy(tPeopleInfo.szAddr1, "Chongqing, China!", strlen("Chongqing, China!"));
- // 對(duì)pszAddr2賦值
- tPeopleInfo.pszAddr2 = "Chengdu, China!";
- // 對(duì)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分配了內(nèi)存空間,然后便可以使用該指針來(lái)接收字符串變量的值(注意,這里是將“Wuhan, China!”賦給了*(tPeopleInfo.pszAddr3))。程序編譯和運(yùn)行都是正常的,輸出結(jié)果如下:
- ~/zhouzx/Test/PointerTest> PointerTest
- Age=10, Addr1=Chongqing, China!, Addr2=Chengdu, China!, Addr3=Wuhan, China!
總結(jié)
本文對(duì)結(jié)構(gòu)體中指針賦值問(wèn)題進(jìn)行了分析,并用C代碼演示了指針的賦值方法。
在實(shí)際的C語(yǔ)言項(xiàng)目中,很多程序出現(xiàn)問(wèn)題,就是對(duì)指針的處理不當(dāng)造成的。因此,熟練掌握各種指針的使用方法,是對(duì)一個(gè)合格的軟件開(kāi)發(fā)人員的基本要求。
【本文是51CTO專欄作者周兆熊的原創(chuàng)文章,作者微信公眾號(hào):周氏邏輯(logiczhou)】