程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C語言中結構體參數變量傳遞簡介

C語言中結構體參數變量傳遞簡介

編輯:關於C語言

在C語言中,結構體參數變量經常作為函數的參數來進行傳遞。但如果參數設置不當,會出現內存問題。

本文以實際的程序代碼為例,詳細地介紹如何正確地使用結構體參數變量,為相關的開發工作提供了參考。

一、前言

本文中的程序實現對員工信息結構體字段賦值並打印出來的功能。該結構體的定義如下:

// 員工信息結構體
    
typedef struct
    
{
    
       INT8       szEmployeeName[100];     // 員工姓名
    
       UINT16  iEmployeeAge;                    // 員工年齡
    
       UINT32  iEmployeeNo;                      // 員工工號
    
} TEmployeeInfo;

函數GetEmployeeInfo用來對員工信息字段進行賦值,其聲明如下:

INT32 GetEmployeeInfo(TEmployeeInfo *ptEmployeeInfo);

在主函數main中,采用兩種參數傳遞的方法,一種是指針傳遞,另一種是非指針傳遞。

二、采用指針傳遞時的程序代碼

采用指針傳遞時的程序代碼如下:

* 修改記錄1:// 修改歷史記錄, 包括修改日期、版本號、修改人及修改內容
    
* 修改日期: 20140617
    
* 版本號: V1.0
    
* 修改人: Zhou Zhaoxiong
    
* 修改內容:創建
    
**********************************************************************/
    
#include <stdio.h>
    
#include <string.h>
    

// 數據類型
    
typedef signed   char INT8;
    
typedef unsigned char UINT16;
    
typedef unsigned int  UINT32;
    
typedef signed   int  INT32;
    

// 員工信息結構體
    
typedef struct
    
{
    
       INT8    szEmployeeName[100];  // 員工姓名
    
       UINT16  iEmployeeAge;         // 員工年齡
    
       UINT32  iEmployeeNo;          // 員工工號
    
} TEmployeeInfo;
    
     
    
     
    
// 函數聲明
    
INT32 GetEmployeeInfo(TEmployeeInfo *ptEmployeeInfo); // 獲取員工信息函數
    
INT32 main(void);
    
     
    
     
    
/****************************************************************
    
* 功能描述:  主函數                                            
    
* 輸入參數:  無                                                 
    
* 輸出參數:  無                                                
    
* 返回值: 0-執行成功  -1-執行失敗                           
    
* 其他說明:  無                                                
    
* 修改日期        版本號        修改人        修改內容
    
* ----------------------------------------------------------------------------------------
    
* 20140617        V1.0      Zhou Zhaoxiong     創建
    
****************************************************************/
    
INT32 main(void)
    
{
    
    INT32          iRetValue      = 0;       // 該變量用於表示調用GetEmployeeInfo函數返回的值
    
    TEmployeeInfo *ptEmployeeInfo = NULL;    // 該變量用於存放員工信息
    
       
    
    // 調用函數對員工信息字段賦值, 並打印出來
    
    iRetValue = GetEmployeeInfo(ptEmployeeInfo);
    
    if (iRetValue != 0)
    
    {
    
        printf("exec GetEmployeeInfo failed.\n");
    
        return -1;
    
    }
    
           
    
    printf("員工信息為: \n姓名: %s\n年齡: %d\n工號: %d\n", ptEmployeeInfo->szEmployeeName, ptEmployeeInfo->iEmployeeAge, ptEmployeeInfo->iEmployeeNo);
    
     
    
    return 0;
    
}
    
     
    
     
    
/**********************************************************************
    
* 功能描述:對員工信息字段賦值
    
* 輸入參數: ptEmployeeInfo: 員工信息結構體
    
* 輸出參數: ptEmployeeInfo: 員工信息結構體
    
* 返回值: 0-成功  -1-失敗
    
* 其它說明:無
    
* 修改日期          版本號           修改人         修改內容
    
* --------------------------------------------------------------------------------------
    
* 20140617           V1.0         Zhou Zhaoxiong      創建
    
***********************************************************************/
    
INT32 GetEmployeeInfo(TEmployeeInfo *ptEmployeeInfo)
    
{
    
    // 先對輸入的指針參數進行異常判斷
    
    if (ptEmployeeInfo == NULL)
    
    {
    
        printf("Input parameter is NULL.\n");
    
        return -1;
    
    }
    
     
    
    strncpy((char *)ptEmployeeInfo->szEmployeeName, "Li Yuanfang", strlen("Li Yuanfang"));   // 對姓名字段賦值
    
    ptEmployeeInfo->iEmployeeAge = 100;       // 對年齡字段賦值
    
    ptEmployeeInfo->iEmployeeNo  = 123456;    // 對工號字段賦值
    
     
    
    return 0;     // 賦值成功, 返回0
    
}

程序的運行結果如圖1所示:

圖1 采用指針傳遞時的程序代碼運行結果

從圖1可以看出,函數GetEmployeeInfo的入參為空,不能實現賦值的功能。

三、改進後的采用指針傳遞時的程序代碼

既然程序打印出指針為空的信息,那麼我們先對傳入的指針進行賦值操作是不是就可以了呢?

改進後的采用指針傳遞時的程序代碼如下:

修改記錄1:// 修改歷史記錄, 包括修改日期、版本號、修改人及修改內容
    
* 修改日期: 20140617
    
* 版本號: V1.0
    
* 修改人: Zhou Zhaoxiong
    
* 修改內容:創建
    
**********************************************************************/
    
#include <stdio.h>
    
#include <string.h>
    
     
    
     
    
// 數據類型
    
typedef signed   char INT8;
    
typedef unsigned char UINT16;
    
typedef unsigned int  UINT32;
    
typedef signed   int  INT32;
    
     
    
     
    
// 員工信息結構體
    
typedef struct
    
{
    
       INT8    szEmployeeName[100];  // 員工姓名
    
       UINT16  iEmployeeAge;         // 員工年齡
    
       UINT32  iEmployeeNo;          // 員工工號
    
} TEmployeeInfo;
    
     
    
     
    
// 函數聲明
    
INT32 GetEmployeeInfo(TEmployeeInfo *ptEmployeeInfo); // 獲取員工信息函數
    
INT32 main(void);
    
     
    
     
    
/****************************************************************
    
* 功能描述:  主函數                                            
    
* 輸入參數:  無                                                
    
* 輸出參數:  無                                                
    
* 返回值: 0-執行成功  -1-執行失敗                           
    
* 其他說明:  無                                                 
    
* 修改日期        版本號        修改人        修改內容
    
* --------------------------------------------------------------------------------------------
    
* 20140617        V1.0      Zhou Zhaoxiong     創建
    
****************************************************************/
    
INT32 main(void)
    
{
    
    INT32          iRetValue      = 0;       // 該變量用於表示調用GetEmployeeInfo函數返回的值
    
    TEmployeeInfo *ptEmployeeInfo = NULL;    // 該變量用於存放員工信息
    
     
    
    // 先對員工信息字段賦值, 防止空指針的存在
    
    strncpy((char *)ptEmployeeInfo->szEmployeeName, "Di Renjie", strlen("Di Renjie"));   // 對姓名字段賦值
    
    ptEmployeeInfo->iEmployeeAge = 150;       // 對年齡字段賦值
    
    ptEmployeeInfo->iEmployeeNo  = 654321;    // 對工號字段賦值
    
       
    
    // 調用函數對員工信息字段賦值, 並打印出來
    
    iRetValue = GetEmployeeInfo(ptEmployeeInfo);
    
    if (iRetValue != 0)
    
    {
    
        printf("exec GetEmployeeInfo failed.\n");
    
        return -1;
    
    }
    
           
    
    printf("員工信息為: \n姓名: %s\n年齡: %d\n工號: %d\n", ptEmployeeInfo->szEmployeeName, ptEmployeeInfo->iEmployeeAge, ptEmployeeInfo->iEmployeeNo);
    
     
    
    return 0;
    
}
    
     
    
     
    
/**********************************************************************
    
* 功能描述:對員工信息字段賦值
    
* 輸入參數: ptEmployeeInfo: 員工信息結構體
    
* 輸出參數: ptEmployeeInfo: 員工信息結構體
    
* 返回值: 0-成功  -1-失敗
    
* 其它說明:無
    
* 修改日期          版本號           修改人         修改內容
    
* -----------------------------------------------------------------------------------
    
* 20140617           V1.0         Zhou Zhaoxiong      創建
    
***********************************************************************/
    
INT32 GetEmployeeInfo(TEmployeeInfo *ptEmployeeInfo)
    
{
    
    // 先對輸入的指針參數進行異常判斷
    
    if (ptEmployeeInfo == NULL)
    
    {
    
        printf("Input parameter is NULL.\n");
    
        return -1;
    
    }
    
     
    
    strncpy((char *)ptEmployeeInfo->szEmployeeName, "Li Yuanfang", strlen("Li Yuanfang"));   // 對姓名字段賦值
    
    ptEmployeeInfo->iEmployeeAge = 100;       // 對年齡字段賦值
    
    ptEmployeeInfo->iEmployeeNo  = 123456;    // 對工號字段賦值
    
     
    
    return 0;     // 賦值成功, 返回0
    
}

程序的運行結果如圖2所示:

圖2 改進後的采用指針傳遞時的程序代碼運行結果

可見,程序出現了內存問題。原因是在傳遞之前,ptEmployeeInfo指針已經指向了確定的地址,不能讓同一個指針同時指向不同的地址。

四、第二次改進後的程序代碼

既然不能用指針作為參數進行傳遞,那麼我們就要考慮另外的方法。

以下代碼采用非指針的傳遞方式:

* 修改記錄1:// 修改歷史記錄, 包括修改日期、版本號、修改人及修改內容
    
* 修改日期: 20140617
    
* 版本號: V1.0
    
* 修改人: Zhou Zhaoxiong
    
* 修改內容:創建
    
**********************************************************************/
    
#include <stdio.h>
    
#include <string.h>
    
     
    
     
    
// 數據類型
    
typedef signed   char INT8;
    
typedef unsigned char UINT16;
    
typedef unsigned int  UINT32;
    
typedef signed   int  INT32;
    
     
    
     
    
// 員工信息結構體
    
typedef struct
    
{
    
       INT8    szEmployeeName[100];  // 員工姓名
    
       UINT16  iEmployeeAge;         // 員工年齡
    
       UINT32  iEmployeeNo;          // 員工工號
    
} TEmployeeInfo;
    
     
    
     
    
// 函數聲明
    
INT32 GetEmployeeInfo(TEmployeeInfo *ptEmployeeInfo); // 獲取員工信息函數
    
INT32 main(void);
    
     
    
     
    
/****************************************************************
    
* 功能描述:  主函數                                            
    
* 輸入參數:  無                                                 
    
* 輸出參數:  無                                                
    
* 返回值: 0-執行成功  -1-執行失敗                           
    
* 其他說明:  無                                                
    
* 修改日期        版本號        修改人        修改內容
    
* --------------------------------------------------------------
    
* 20140617        V1.0      Zhou Zhaoxiong     創建
    
****************************************************************/
    
INT32 main(void)
    
{
    
    INT32         iRetValue     = 0;      // 該變量用於表示調用GetEmployeeInfo函數返回的值
    
    TEmployeeInfo tEmployeeInfo = {0};    // 該變量用於存放員工信息
    
       
    
    // 調用函數對員工信息字段賦值, 並打印出來
    
    iRetValue = GetEmployeeInfo(&tEmployeeInfo);
    
    if (iRetValue != 0)
    
    {
    
        printf("exec GetEmployeeInfo failed.\n");
    
        return -1;
    
    }
    
           
    
    printf("員工信息為: \n姓名: %s\n年齡: %d\n工號: %d\n", tEmployeeInfo.szEmployeeName, tEmployeeInfo.iEmployeeAge, tEmployeeInfo.iEmployeeNo);
    
     
    
    return 0;
    
}
    
     
    
     
    
/**********************************************************************
    
* 功能描述:對員工信息字段賦值
    
* 輸入參數: ptEmployeeInfo: 員工信息結構體
    
* 輸出參數: ptEmployeeInfo: 員工信息結構體
    
* 返回值: 0-成功  -1-失敗
    
* 其它說明:無
    
* 修改日期          版本號           修改人         修改內容
    
* --------------------------------------------------------------
    
* 20140617           V1.0         Zhou Zhaoxiong      創建
    
***********************************************************************/
    
INT32 GetEmployeeInfo(TEmployeeInfo *ptEmployeeInfo)
    
{
    
    // 先對輸入的指針參數進行異常判斷
    
    if (ptEmployeeInfo == NULL)
    
    {
    
        printf("Input parameter is NULL.\n");
    
        return -1;
    
    }
    
     
    
    strncpy((char *)ptEmployeeInfo->szEmployeeName, "Li Yuanfang", strlen("Li Yuanfang"));   // 對姓名字段賦值
    
    ptEmployeeInfo->iEmployeeAge = 100;       // 對年齡字段賦值
    
    ptEmployeeInfo->iEmployeeNo  = 123456;    // 對工號字段賦值
    
     
    
    return 0;     // 賦值成功, 返回0
    
}

程序的執行結果如圖3所示:

圖3第二次改進後的程序代碼執行結果

從圖3可以看出,程序執行結果正確,得到了我們想要的結果。

五、總結

在編寫代碼的過程中,我們需要注意以下方面:

(1) 程序頭部、函數頭部及重要的程序語句處一定要有注釋,這體現了軟件開發人員的專業素養。

(2) 函數中出現的變量在定義的同時要進行初始化,函數在調用之前一定要先進行聲明。

(3) 對於函數中的指針變量參數,在使用之前一定要先進行異常判斷(即判斷其是否為NULL)。

(4) 對於有返回值的函數,要用不同的返回值來區別不同的執行結果,並在重要的地方打印出提示信息,方便對代碼的調試。

指針是C語言的精華所在,同時也是難點所在。對於一個合格的軟件開發工程師來說,一定要熟練掌握指針的使用方法。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved