【C语言】嵌套结构体初始化 - 一个有趣的结论

news2024/11/29 0:42:08
 0. 前言

        A. 嵌套结构体(比如双链表)的初始化一般是什么流程?

        B. 嵌套结构体的内存是如何分布的?

        C. 结构体中的结构体指针是否需要再次分配内存?不分配会怎么样?

        关于嵌套结构体的初始化问题,我找了网上的一些资料,发现能够解决我上述疑问的文章,自己试验后总结一下,欢迎交流。

1. 试验代码:

        如下代码实现的功能是这样的:假设有一本空白的本子,你可以使用addPage函数按顺序从第一页开始写入内容,并且可以通过prePage和nextPage查看已经写入的内容。

#include <stdio.h>
#include <stdlib.h>

typedef struct page_info{
    int index;
    const char *contents;
    struct page_info *pre;
    struct page_info *next;
}PAGE_INFO;

typedef struct {
    int page_num;               // 一本书一共有多少页可以写;
    int count;                  // 记录当前写了多少页;
    struct page_info *head;
    struct page_info *end;
    struct page_info *current;
} BOOK;

static BOOK *BOOKCreate(const char *homepage, int page_num)
{
    BOOK *sys = (BOOK *)malloc(sizeof(BOOK));
    sys->page_num = page_num;
    printf("head address is %x\n",sys->head);
    sys->head = (PAGE_INFO *)malloc(sizeof(PAGE_INFO));
    sys->end = (PAGE_INFO *)malloc(sizeof(PAGE_INFO));
    sys->current = (PAGE_INFO *)malloc(sizeof(PAGE_INFO));
    printf("head address is %x\n",sys->head);
    sys->count = 1;
    sys->head->index = 1;
    sys->head->pre = NULL;
    sys->head->next = NULL;
    sys->head->contents = homepage;
    sys->end = sys->head;
    sys->current = sys->head;
    return sys;
}

int addPage(BOOK *sys, const char *contents){
    PAGE_INFO *temp = (PAGE_INFO *)malloc(sizeof(PAGE_INFO));
    temp->contents = contents;
    temp->index = sys->current->index + 1;

    sys->end->next = temp;
    temp->pre = sys->end;

    sys->end = temp;
    sys->count ++;
    return sys->count;
}

const char *prePage(BOOK *sys)
{
    if (sys->current->pre != NULL){
        sys->current = sys->current->pre;
    }
    return sys->current->contents;
}

const char *nextPage(BOOK *sys){
    if (sys->current->next != NULL){
        sys->current = sys->current->next;
    }
    return sys->current->contents;
}

static void BOOKFree(BOOK *sys)
{
    free(sys);
}

int main() {
    printf("size of int is %d\n",sizeof(int));
    printf("size of PAGE_INFO is %d\n",sizeof(PAGE_INFO));
    printf("size of BOOK is %d\n",sizeof(BOOK));

    BOOK *sys = BOOKCreate("this is first page.",100);
    printf("%s\n",prePage(sys));
    printf("%d\n",addPage(sys,"this is second page"));
    printf("%s\n",nextPage(sys));
    printf("%s\n",prePage(sys));
    BOOKFree(sys);
    return 0;
}

上述代码执行结果:

 2. 试验一:

        上述代码不做改动的情况下,我们可以得到如下结论:

        1). BOOKCreate函数在调用malloc时,已经给head/end/current这些结构体指针分配了地址;

        2). 因为结构体内存分配时要遵循对齐原则(详情可参考这篇文章),BOOK和PAGE_INFO结构体都占用了32个字节,符合预期;

3. 试验二:

        基于第二小节的第一个结论,我们对上述代码做如下调整,即,注释掉再次给head/end/current分配堆内存的操作,应该也能正常运行。我们可以看下运行效果:

做上述注释,然后再次运行:

 结果:

        1. 我们可以看到对sys结构体指针分配内存后,sys->head的内存也已经分配好了,做如上注释后,sys->head的地址没有发生变动;

        2. 程序异常退出,不符合预期;

4. 为什么?

        我们用IDE debug,单步运行,发现在第一次使用sys->head的时候,程序就已经报错了:

        这里我们可以看到sys->head/sys->end/sys->current的地址每次执行都是这个0xbaadf00d,有点奇怪。那这个地址又是什么?

 从网上找到了一些资料大家可以参考:地址。资料中提到:

LocalAlloc/GlobalAlloc,如果指定的是LMEM_FIXED(默认就指定了这个),并且没有指定LMEM_ZEROINIT,则分配的内存中初始化值为BAADF00D(可以理解成badfood,也就是不能直接吃的意思,呵呵)。调用LocalFree/GlobalFree则其值会变为FEEEFEEE)可以理解成Free)。

哈哈哈,badfood 

        到这里我们就很容易得到结论了,结构体使用malloc初始化时,结构体中的指针并没有被分配地址,我们需要通过使用malloc分配内存。(注,第3小节的时延不同的环境打印的结果不同,但是结论一致)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1192255.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Element-Plus表单label实现两端对齐(左右对齐)

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; 在使用Element-Plus的form的时候,label只有左右,居中对齐&#xff0c;缺少两端对齐的选项 故研究一下如何实现&#xff0c;其他方法也试过&#xff0c;都没效果&#xff0c;我在别人的基础上又研究了一…

【深度学习】深度学习下的语音识别

语音识别正在侵入我们的生活。它内置于我们的手机、游戏机和智能手表中。它甚至使我们的房屋自动化。你只需 50 美元&#xff0c;你就可以获得一个 Amazon Echo Dot——一个神奇盒子&#xff0c;你只需大声说出你的需求就可以帮你订购披萨、获取天气预报甚至购买垃圾袋。 但是…

【机器学习】给大家推荐几个资源

我写博客的目的就是让大家了解人工智能背后的数学原理&#xff0c;但人工智能这个话题太大了&#xff0c;背后涉及到的知识非常庞大&#xff0c;仅靠写几篇文章传播力度有限&#xff0c;况且知识传播过程中也容易引入误解&#xff0c;所以授之以鱼不如授之以渔&#xff0c;这里…

LiveMedia视频监控汇聚管理平台方案(三)

上一篇文章中我们介绍了LiveMedia视频监控汇聚管理平台视频接入方案中功能设计的设备接入方法。在这篇文章中我们来介绍下LiveMedia视频监控汇聚管理平台方案中功能设计里的流媒体转发是如何实现的&#xff1f; 图1流媒体转发框架 平台流媒体转发框架如图1流媒体转发框架所示&a…

AutoGluon:亚马逊自动机器学习工具,初学者的福音

如果一个机器学习初学者&#xff0c;仅用三行代码就训练了一个模型&#xff0c;并且模型的性能要比从业数十年的都要好&#xff0c;这是一种什么样的感觉&#xff1f; AutoGluon就能帮你梦想成真。 上面这张图片就是AutoGluon的工作流&#xff0c;多么简单啊&#xff01;根据数…

网站接口测试记录

1.被测试服务器端口输入htop指令进行cpu监控 2.测试机器安装宝塔-》我的工具-》进行网站测试 访问地址&#xff1a;https://www.bt.cn/bbs/thread-52772-1-1.html

【FGPA】Verilog:移位寄存器 | 环形计数器 | 4bit移位寄存器的实现 | 4bit环形计数器的实现

目录 Ⅰ. 理论部分 0x00 移位寄存器&#xff08;Shift Register&#xff09; 0x01 环形计数器&#xff08;Ring Counter&#xff09; Ⅱ. 实践部分 0x00 移位寄存器&#xff08;4-bit&#xff09; 0x01 四位环形寄存器&#xff08;4-bit&#xff09; Ⅰ. 理论部分 0x00 …

springboot+vue健美操评分系统的设计与实现【内含源码+文档+部署教程】

博主介绍&#xff1a;✌全网粉丝10W,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业毕业设计项目实战6年之久&#xff0c;选择我们就是选择放心、选择安心毕业✌ &#x1f345;由于篇幅限制&#xff0c;想要获取完整文章或者源码&#xff0c;或者代做&am…

YOLOv8-Seg改进: 分割小目标系列篇 | SPD-Conv,提升分割小目标和弱小分割图精度

🚀🚀🚀本文改进:SPD-Conv由一个空间到深度(SPD)层和一个无卷积步长(Conv)层组成,可以应用于大多数CNN体系结构,特别是在处理低分辨率图像和分割小目标等更困难的任务时。 🚀🚀🚀SPD-Conv 分割小目标检测首选,暴力涨点 🚀🚀🚀YOLOv8-seg创新专栏:http:…

剑指JUC原理-16.读写锁

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring源码、JUC源码&#x1f525;如果感觉博主的文章还不错的话&#xff0c;请&#x1f44d;三连支持&…

炮炮面试——简历中专业技能

自我介绍: 面试官,您好! 我叫XXX,今年25岁,目前是XXX大学电子信息学院研三的一名学生,面试岗位是前端研发工程师。下面我将从以下几个方面来介绍自己: (学习能力)在校期间通过了英语四六级、以及一些计算机专业证书,成绩一直是专业前5%,每年都获得学…

Elastic Stack 8.11:引入一种新的强大查询语言 ES|QL

作者&#xff1a;Tyler Perkins, Ninoslav Miskovic, Gilad Gal, Teresa Soler, Shani Sagiv, Jason Burns Elastic Stack 8.11 引入了数据流生命周期、一种配置数据流保留和降采样&#xff08;downsampling&#xff09; 的简单方法&#xff08;技术预览版&#xff09;&#xf…

LiveMedia视频监控汇聚管理平台视频接入方案(二)

上一篇文章中我们介绍了LiveMedia视频监控汇聚管理平台技术方案的架构。今天我们来介绍下LiveMedia视频监控汇聚管理平台的视频接入方案。 视频集控平台建设充分考虑利旧的建设原则&#xff0c;同时根据各个现有视频监控建设情况&#xff0c;考虑统一规划、分布实施的建设方式。…

电脑怎么录制视频,录制的视频怎么剪辑?

在现今数字化的时代&#xff0c;视频成为了人们日常生活中不可或缺的一部分。因此&#xff0c;对于一些需要制作视频教程、录制游戏或者是进行视频演示的人来说&#xff0c;电脑录屏已经成为了一个必不可少的工具。那么&#xff0c;对于这些人来说&#xff0c;如何选择一个好用…

Mysql视图应用

现在&#xff0c;我们将创建一个视图&#xff0c;将员工的姓名、部门和工资信息组合在一起。 CREATE VIEW EmployeeSalaryView AS SELECT e.FirstName, e.LastName, e.Department, s.MonthlySalary FROM Employees e JOIN Salary s ON e.EmployeeID s.EmployeeID;通过这个视图…

MySQL大表数据导入到MongoDB

修改参数 &#xff0c;开启into outfile的功能 secure_file_priv/home/backups/mysql_outfile 重启数据库是参数生效 按条件导出MySQL数据 select * from receipt_receive_log where gmt_create > 2020-04-13 00:00:00 and gmt_create< 2020-07-13 00:00:00 INTO O…

Azure 机器学习 - 有关为 Azure 机器学习配置 Kubernetes 群集的参考

目录 受支持的 Kubernetes 版本和区域建议的资源计划ARO 或 OCP 群集的先决条件禁用安全增强型 Linux (SELinux)ARO 和 OCP 的特权设置 收集的日志详细信息Azure 机器学习作业与自定义数据存储连接支持的 Azure 机器学习排斥和容许最佳实践 通过 HTTP 或 HTTPS 将其他入口控制器…

面试题:在 Java 中 new 一个对象的流程是怎样的?彻底被问懵了。。

文章目录 前言JVM内存JVM生成.class文件类加载器加载.class文件知识扩展&#xff1a;Class对象首先搞清楚 newInstance 两种方法区别&#xff1a; 连接和初始化创建实例 前言 对象怎么创建&#xff0c;这个太熟悉了&#xff0c;new一下(其实还有很多途径&#xff0c;比如反射、…

EAS 去除重复的 职位 组织树信息

--备份 SELECT * into T_PM_ORGRANGE_bak1110 FROM T_PM_ORGRANGE --检查是否备份成功 select count(1) from T_PM_ORGRANGE_bak1110 --查询是否有重复脏数据 SELECT FORGID,FUSERID,FTYPE FROM T_PM_ORGRANGE group by FORGID,FUSERID,FTYPE having count(1)>1 --删除脏数据…

推送效率低?MobPush带着APP消息推送一站式解决方案来了

随着移动应用竞争的日趋激烈&#xff0c;如何拉新促活&#xff0c;保持用户粘性成为各大APP的运营的焦点和核心。作为一种有效的营销和用户保留工具。APP消息推送可以有效提高用户参与度&#xff0c;增强用户忠诚度&#xff0c;并最终提高业务效益。然而随着各大APP推送的高度同…