结构体中指针赋值问题的分析及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语言项目中,很多程序出现问题,就是对指针的处理不当造成的。因此,熟练掌握各种指针的使用方法,是对一个合格的软件开发人员的基本要求。

时间: 2024-10-10 11:28:07

结构体中指针赋值问题的分析及C代码示例的相关文章

结构体中函数指针与typedef关键用途(函数指针)

// 结构体函数指针.  #include<stdio.h> //为了代码的移植考虑,一般使用typedef定义函数指针类 ,另一个好处是,减少代码的书写量.  typedef void (*shout)(char *name,int age); typedef struct {  //用指针来存储字符串     char *name;    int age ;    shout personinfo; }person; //类似于c++中类方法的实现,在这里,是为结构体中指针函数提供实现.在

结构体中定义函数指针

转自:http://blog.csdn.net/unix21/article/details/9293877 结构体指针变量的定义,定义结构体变量的一般形式如下: 形式1:先定义结构体类型,再定义变量 struct结构体标识符 { 成员变量列表;… }; struct 结构体标识符 *指针变量名; 变量初始化一:struct结构体标识符 变量名={初始化值1,初始化值2,…, 初始化值n }; 形式2:在定义类型的同时定义变量 struct结构体标识符 { 成员变量列表;… } *指针变量名;

go语言 从结构体中获取某个字段的值(反射+泛型)

Go 语言提供了 user.Name 语法,来从 user 结构体中获取 Name 的值. 那么如果我们想将 Name 变成变量该如何做呢? 原型:getStructField(input interface{}, key string) (value interface{}, err error) 功能:从 input 结构体中,取出 key 字段 对应的值 代码实现: package utils import ( "errors" "fmt" "ref

C/C++ 错误笔记-在给结构体中的指针赋值时,要注意该指针是否已指向内存空间

先来看下面的例子: #include <stdlib.h> #include <string.h> #include <stdio.h> #pragma warning(disable:4996) typedef struct _Student { char name[64]; int age; }Student; typedef struct _Teacher { char name[64]; int age; char *p1; char **p2; Student

C语言中结构体变量之间赋值

最近,我阅读了某新员工小刘写的C语言代码,发现其对结构体变量之间的赋值不是很熟悉.对于两个相同类型的结构体变量,他均采用的是逐个成员变量直接赋值的形式.如下的代码示例: 如上代码所示,tEmployeeInfoSrc和tEmployeeInfoDest是两个类型相同的结构体变量,tEmployeeInfoSrc(源结构体变量)中的各个成员变量已赋初值.现要使tEmployeeInfoDest(目的结构体变量)中的各个成员变量的值与tEmployeeInfoSrc中对应成员变量的值相同.小刘采用的

file结构体中private_data指针的疑惑【转】

本文转载自:http://www.cnblogs.com/pengdonglin137/p/3328984.html hi all and barry, 最近在学习字符设备驱动,不太明白private_data在字符驱动中的作用,我们在 驱动中添加一个设备结构体,然后定义了这个结构体的全局指针变量,接着我们就能在 驱动程序中使用这个指针了.我看到很多驱动程序中都把结构体指针付给private_data, 然后对private_data操作. 为什么要使用private_data,难道仅仅是避免使

【C语言】用结构体数组指针完成:有三个学生信息,存放在结构体数组中,要求输出全部信息

//用结构体数组指针完成:有三个学生信息,存放在结构体数组中,要求输出全部信息 #include <stdio.h> struct Stu { int num; char name[20]; char sex; int age; }; int main() { struct Stu student[3]={{317,"han",'m',20},{318,"hun",'w',22},{311,"dan",'w',18}}; struct

C语言结构体中的函数指针

这篇文章简单的叙述一下函数指针在结构体中的应用,为后面的一系列文章打下基础 本文地址:http://www.cnblogs.com/archimedes/p/function-pointer-in-c-struct.html,转载请注明源地址. 引言 指针是C语言的重要组成部分, 于是深入理解指针并且高效地使用指针可以使程序员写出更加老练的程序.我们要记住指针是一个指向内存地址的变量.指针可以引用如int.char……常见的数据类型,例如: int * intptr; // 声明一个指向整型值的

当结构体遇上宏定义,以及函数指针的高级写法(结构体中能用宏定义一个函数?)

一.结构体中可以定义一般的宏定义 如: struct aaa{   #define STATUS_1 100   #define STATUS_2 200   #define STATUS_3 300   ........}: 首先,这里的宏定义是在预编译阶段完成的,编译器此时并不知道什么结构体,所以这些宏是全局可见的.   一个宏定义,如果写在结构体之内,即使与结构体之外的宏定义名字重复了最多是编译警告.可是如果不在结构体之内,名字重复可肯定是error.(未证实,可以做实验,而且可以把两处的