問題描述
某結構體的定義如下:

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語言專案中,很多程式出現問題,就是對指標的處理不當造成的。因此,熟練掌握各種指標的使用方法,是對一個合格的軟體開發人員的基本要求。