IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言结构体传参 -> 正文阅读

[C++知识库]C语言结构体传参

C语言结构体传参

结构体传参包括三种传参方式

  1. 普通传参:函数接收到结构体参数后,会复制一份原来的结构体作为形参供函数使用,而函数内的任何操作都是对拷贝结构体的修改,不会影响到原本的结构体变化。
  2. 单指针传参:函数接收的是一个结构体的地址,该指针指向的是结构体起始地址,也就相当于传入了结构体内所有变量的地址,函数接收到该结构体指针后,我们就可以根据地址访问结构体中每个变量的真实数据,在函数内对结构体内数据的操作,都会影响到原本结构体内数据的变化
  3. 双指针传参:函数接收的是结构体指针变量的地址,因为一级指针代表的是结构体的地址,在函数中能够操作结构体内的数据,则二级指针指向的是结构体的地址,则同理我们可以根据二级指针访问修改结构体的地址
    即通过一级指针,对结构体内数据的操作会影响到原本结构体内数据的变化
    而通过二级指针,对结构体地址的操作会影响到原本结构体地址的变化,例如为结构体分配空间

1. 普通传参

1.1 测试代码

#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
    int age;
    struct Node *next;
} Node;

// 普通传参
void test(Node p)
{

    printf("test():\n");

    printf("数据: p.age = %d\n", p.age);
    printf("地址: p = %x, p->next = %x\n\n", &p, p.next);

    // 在函数内定义一个新的结构体
    Node q;
    q.age = 3;
    q.next = NULL;
    
    // 修改结构体内的数据
    p.age = 2;
    p.next = &q;
    printf("数据: p.age = %d\n", p.age);
    printf("地址: p = %x, p->next = %x\n", &p, p.next);

    printf("数据: q.age = %d\n", q.age);
    printf("地址: q = %x, q->next = %x\n\n", &q, q.next);
}

int main()
{
    Node p;
    p.age = 1;
    p.next = NULL;

    printf("main():\n");
    printf("数据: p.age=%d\n", p.age);
    printf("地址: p=%x, p->next=%x\n\n", &p, p.next);

    test(p);

    printf("main():\n");
    printf("数据: p.age=%d\n", p.age);
    printf("地址: p=%x, p->next=%x\n\n", &p, p.next);

    return 0;
}

1.2 测试结果

在这里插入图片描述

1.3 结果分析

由结果可得,通过普通传参

  • 函数内的操作对原结构体没有影响
  • p结构体的地址、数据均未发生变化

其流程如下图:
在这里插入图片描述

2. 单指针传参

2.1 修改结构体数据

2.1.1 测试代码

#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
    int age;
    struct Node *next;
}Node;

// 单指针传参,修改结构体数据
void ModifyData(Node *p)
{
    printf("ModifyData:\n");

    printf("数据: p.age = %d\n", p->age);
    printf("地址: p = %x, p->next = %x\n\n", p, p->next);

    // 在函数内定义一个新的结构体
    Node q;
    q.age = 3;
    q.next = NULL;
    
    // 修改数据(age,next)
    p->age = 2;
    p->next = &q;

    printf("数据: p.age = %d\n", p->age);
    printf("地址: p = %x, p->next = %x\n\n", p, p->next);

    printf("数据: q.age = %d\n", q.age);
    printf("地址: q = %x, q->next = %x\n\n", &q, q.next);

}

int main()
{
    Node p;
    p.age = 1;
    p.next = NULL;

    printf("main():\n");
    printf("数据: p.age = %d\n", p.age);
    printf("地址: p = %x, p->next = %x\n\n", &p, p.next);

    ModifyData(&p);

    printf("main():\n");
    printf("数据: p.age = %d\n", p.age);
    printf("地址: p = %x, p->next = %x\n\n", &p, p.next);

    return 0;
}

2.1.2 测试结果

在这里插入图片描述

2.1.3 结果分析

通过ModifyData()函数,由以上测试结果可得

  • p结构体内的数据发生了变化
  • p结构体的原地址没有发生变化

所以通过结构体的地址,我们可以找到数据的真实地址,进而修改真实数据
在这里插入图片描述

2.2 修改结构体地址

2.2.1 测试代码

#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
    int age;
    struct Node *next;
}Node;

// 单指针传参, 尝试修改结构体地址
Node *ModifyAddress(Node *p)
{
    printf("ModifyAddress():\n");

    printf("数据: p.age = %d\n", p->age);
    printf("地址: p = %x, p->next = %x\n", p, p->next);
    printf("形参指针变量p的地址 = %x\n\n", &p);

    // 尝试为指针重新分配地址,并修改原本结构体内部数据
    p = (Node *)malloc(sizeof(Node));
    p->age = 4;
    p->next = NULL;

    printf("数据: p.age = %d\n", p->age);
    printf("地址: p = %x, p->next = %x\n", p, p->next);
    printf("形参指针变量p的地址 = %x\n\n", &p);

    // 返回修改后的结构体指针p
    return p;
}

int main()
{
    Node p;
    p.age = 1;
    p.next = NULL;

    printf("main():\n");
    printf("数据: p.age = %d\n", p.age);
    printf("地址: p = %x, p->next = %x\n\n", &p, p.next);

    Node *new_p = ModifyAddress(&p);

    printf("main():\n");
    printf("数据: p.age = %d\n", p.age);
    printf("地址: p = %x, p->next = %x\n", &p, p.next);

    printf("数据: new_p.age = %d\n", new_p->age);
    printf("地址: new_p = %x, new_p->next = %x\n\n", new_p, new_p->next);

    return 0;
}

2.2.2 测试结果

在这里插入图片描述

2.2.3 结果分析

由以上结果可得,在调用函数体内修改结构体的地址,对原结构体A没有任何影响,因为在调用函数体内修改了形参p的地址,就代表了指针p指向了另一片结构体空间B,如果修改结构体B的内容,这对结构体A来说完全就是八竿子打不着。
在这里插入图片描述
由上图我们可以知道,我们在函数内重新开辟了一个新的结构体空间 [731250],而通过动态开辟的空间在函数调用完毕后是不会被释放的,所以在函数调用完毕后,我们仍然可以通过地址 [731250] 访问该结构体的数据,而如果不再使用,我们应该及时释放掉该空间free()

3. 双指针传参

3.1 测试代码

#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
    int age;
    struct Node *next;
} Node;

// 双指针传参
void test(Node **p)
{

    printf("test:\n");
    printf("数据: p.age = %d\n", (*p)->age);
    printf("地址:p = %x, (*p) = %x, (*p)->next = %x\n", p, (*p), (*p)->next);
    printf("指针p的地址 = %x\n\n", &p);
    
    // 在函数内定义一个新的结构体
    Node q;
    q.age = 3;
    q.next = NULL;
    

    // 为结构体(*p)重新分配地址,并修改变量数据
    (*p) = (Node *)malloc(sizeof(Node));
    (*p)->age = 2;
    (*p)->next = &q;
    
    printf("数据: p.age = %d\n", (*p)->age);
    printf("地址:p = %x, (*p) = %x, (*p)->next = %x\n", p, (*p), (*p)->next);
    printf("指针p的地址 = %x\n\n", &p);

    printf("数据: q.age = %d\n", q.age);
    printf("地址: q = %x, q->next = %x\n\n", &q, q.next);
}

int main()
{

    Node *p;
    // 为指针结构体p分配地址
    p = (Node *)malloc(sizeof(Node));
    p->age = 1;
    p->next = NULL;

    printf("main():\n");
    printf("数据: p.age = %d\n", p->age);
    printf("地址: p = %x, p->next = %x\n", p, p->next);
    printf("指针p的地址 = %x\n\n", &p);

    test(&p);

    printf("main():\n");
    printf("数据: p.age = %d\n", p->age);
    printf("地址: p = %x, p->next = %x\n", p, p->next);
    printf("指针p的地址 = %x\n\n", &p);

    return 0;
}

3.2 测试结果

在这里插入图片描述

3.2 结果分析

由结果可得,通过双指针传参,我们可以对结构体的数据和地址都做出实际修改。
其流程如下图:
在这里插入图片描述

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-31 23:45:54  更:2022-03-31 23:49:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:16:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码