结构体指针的使用与讨论

[复制链接]
615|24
 楼主 | 2017-12-23 15:24 | 显示全部楼层 |阅读模式
如题,我们在使用结构体的时候,也会经常见到结构体指针的定义与使用的,,本来结构体对初学者来说就很复杂了,再加上指针的,就更加木乱的,,如下边这个定义的,如何去理解的呢?
 楼主 | 2017-12-23 15:25 | 显示全部楼层
结构体的定义如下:

typedef struct
{
    int     iAge;                // 年龄
    char    szAddr1[100];        // 地址1
    char   *pszAddr2;            // 地址2
    char  **pszAddr3;            // 地址3
} T_PeopleInfo;
第一个年龄的成员int类型,好理解的哈
 楼主 | 2017-12-23 15:38 | 显示全部楼层
pszAddr2和pszAddr3均为指针,其中pszAddr2为一级指针,pszAddr3为二级指针,,这个怎么理解的呢?
 楼主 | 2017-12-23 15:40 | 显示全部楼层
结合具体的实例来分析的哈,,
看如下例程的:
#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;
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;
}
 楼主 | 2017-12-23 15:43 | 显示全部楼层
实际运行的时候,会发现:对结构体中的数组的赋值方法对指针赋值,程序可以编译通过,但运行的时候,程序便会挂掉。究其原因,是因为没有为pszAddr2和pszAddr3指针分配内存空间。

于是,重新对main函数进行修改的,,如下:
 楼主 | 2017-12-23 15:43 | 显示全部楼层
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;
}
 楼主 | 2017-12-23 15:44 | 显示全部楼层
这里,使用malloc为pszAddr2和pszAddr3分配了内存空间(注意,执行malloc之后,要判断指针是否为空),此时就可以将变量值赋给它们。程序编译和运行都是正常的,输出结果如下:

Test/PointerTest> PointerTest
Age=10, Addr1=Chongqing, China!, Addr2=Chengdu, China!, Addr3=Wuhan, China!
 楼主 | 2017-12-23 15:47 | 显示全部楼层
本帖最后由 tongbu2015 于 2017-12-23 15:52 编辑

直接将字符,串赋给了pszAddr2和pszAddr3,也就是将这两个字符串的首地址赋给了指针。那么,指针所指向的地址中存放的内容就是字符串的值。现在是正确了哈,,那么我们就会问了,,既然是指针的,可不可以直接的进行复制操作的呢?
答案是肯定的,,
于是,有了如下修改:
 楼主 | 2017-12-23 15:47 | 显示全部楼层
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;
}
 楼主 | 2017-12-23 15:50 | 显示全部楼层
这里可以看到,是直接给一级指针、二级指针进行复制操作的,,是可以的,
那么问题又来了,,难道一级指针与二级指针的用法是一样的么?这里复制不是一样么?
答案若是,那么,我们定义二级指针的是作何用么?
其实阿是有区别的,我们又重新修改了下main函数的,注意与上文的区别的哈
 楼主 | 2017-12-23 15:54 | 显示全部楼层
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;
}
这里在对pszAddr3赋值时,在tPeopleInfo.pszAddr3前加了一个*的,,,
 楼主 | 2017-12-23 15:55 | 显示全部楼层
先用malloc为pszAddr3分配了内存空间,然后便可以使用该指针来接收字符串变量的值(注意,这里是将“Wuhan, China!”赋给了*(tPeopleInfo.pszAddr3))。程序编译和运行都是正常的,输出结果如下:

Test/PointerTest> PointerTest
Age=10, Addr1=Chongqing, China!, Addr2=Chengdu, China!, Addr3=Wuhan, China!

输出结果跟上文是一样的哈
 楼主 | 2017-12-23 15:57 | 显示全部楼层
这里还要注意最后那个修改用例的:printf("Age=%d, Addr1=%s, Addr2=%s, Addr3=%s\n", tPeopleInfo.iAge, tPeopleInfo.szAddr1, tPeopleInfo.pszAddr2, *(tPeopleInfo.pszAddr3));
tPeopleInfo.pszAddr3,,也加了一个*的
| 2017-12-23 15:59 | 显示全部楼层
楼主说了这么多的,,我也大致的对结构体指针的用法大致了解下的,但是就这一级指针、二级指针的,还是有疑问的,看着也还是没啥区别的呀
| 2017-12-23 16:00 | 显示全部楼层
刚才百度了一下的,,二级指针的,,大概意思就是指向指针的指针——A(即B的地址)是指向指针的指针,称为二级指针,用于存放二级指针的变量称为二级指针变量.根据B的不同情况,二级指针又分为指向指针变量的指针和指向数组的指针.
| 2017-12-23 16:01 | 显示全部楼层
二级指针的概念

首先任何值都有地址 ,一级指针的值虽然是地址,但这个地址做为一个值亦需要空间来存放,是空间就具有地址 ,这就是存放地址这一值的空间所具有的地址,二级指针就是为了获取这个地址。
| 2017-12-23 16:03 | 显示全部楼层
一级指针所关联的是其值(一个地址)名下空间里的数据,这个数据可以是任意类型并做任意用途,但二级指针所关联的数据只有一个类型一个用途,就是地址,指针就是两个用途提供目标的读取或改写, 那么二级指针就是为了提供对于内存地址的读取或改写。
| 2017-12-23 16:05 | 显示全部楼层
更通俗一点理解解释的——指针的表现形式是地址,核心是指向关系指针,运算符"*"的作用是按照指向关系访问所指向的对象.如果存在A指向B的指向关系,则A是B的地址,"*A"表示通过这个指向关系间接访问B.如果B的值也是一个指针,它指向C,则B是C的地址,"*B"表示间接访问C;
如果C是整型、实型或者结构体等类型的变量或者是存放这些类型的数据的数组元素,则B(即C的地址)是普通的指针,称为一级指针,用于存放一级指针的变量称为一级指针变量。
| 2017-12-28 23:41 | 显示全部楼层
这里还设计到一个二级指针的操作的哈
| 2017-12-29 08:47 | 显示全部楼层
结构体指针用的少
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式
我要创建版块 申请成为版主

论坛热帖

快速回复 返回顶部 返回列表