第五十五天学习记录:C语言进阶:动态内存管理Ⅲ

news2024/11/27 10:28:12

柔性数组

C99中,结构中的最后一个元素允许是未知大小的数组,这就叫做柔性数组成员。

柔性数组的特点:
。结构体中的柔性数组成员前面必须至少有一个其他成员。
。sizeof返回的这种结构大小不包括柔性数组的内存。
。包含柔性数组成员的结构用malloc()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

struct S
{
	int n;
	int arr[];//未知大小的-柔性数组成员-数组的大小是可以调整的
};

int main()
{
	struct S s;
	printf("%d\n", sizeof(s));//4
	return 0;
}

第一种写法:

#define _CRT_SECURE_NO_WARNINGS 1

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

struct S
{
	int n;
	int arr[0];//未知大小的-柔性数组成员-数组的大小是可以调整的
};

int main()
{
	struct S* ps =(struct S*)malloc(sizeof(struct S)+5*sizeof(int));
	ps->n = 100;
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		ps->arr[i] = i;//0 1 2 3 4
	}
	struct S* ptr = realloc(ps, 44);
	if (ptr != NULL)
	{
		ps = ptr;
	}
	for (i = 5; i < 10; i++)
	{
		ps->arr[i] = i;//5 6 7 8 9
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	//释放
	free(ps);
	ps = NULL;
	return 0;
}

第二种写法(替代柔性数组):

#define _CRT_SECURE_NO_WARNINGS 1

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

struct S
{
	int n;
	int* arr;
};

int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S));
	ps->arr = malloc(5 * sizeof(int));
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		ps->arr[i] = i;//0 1 2 3 4
	}
	for (i = 0; i < 5; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	//调整大小
	int* ptr=realloc(ps->arr, 10*sizeof(int));
	if (ptr != NULL)
	{
		ps->arr = ptr;
	}
	for (i = 5; i < 10; i++)
	{
		ps->arr[i] = i;//5 6 7 8 9
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	//释放
	free(ps->arr);
	ps->arr = NULL;
	free(ps);
	ps = NULL;
	return 0;
}

柔性数组的两个好处:
好处一:
方便内存释放
好处二:
这样有利于访问速度

问:柔性数组的结构体为什么前面需要有一个int?
ChatAI答:
柔性数组是指结构体中的最后一个元素是不定长数组,其长度在运行时才确定。柔性数组通常用于动态地管理一些变长数据的情况,如字符串、动态数组、缓冲区等。

在定义一个包含柔性数组的结构体时,需要保证柔性数组是结构体的最后一个元素,这是因为结构体分配内存时,其大小是根据结构体中所有元素的大小之和来确定的,而不定长数组的大小是根据运行时动态分配的,因此只有放在最后一个元素位置上才能保证整个结构体的大小是确定的。

然而,由于 C 语言没有提供直接动态定义结构体的方式,即不确定结构体的大小,所以需要为柔性数组的结构体指定一个固定大小,默认情况下为 0。这个固定大小的长度表示柔性数组前面的元素个数,一般使用 int 类型,具体大小根据实际情况而定。

例如,下面是一个包含柔性数组的结构体的示例,其中 data 是一个不定长数组,count 表示数组元素个数:

struct flex_array {
    int count;      // 柔性数组前面的元素个数
    int data[];     // 不定长数组,必须放在结构体最后
};

对于这个结构体,可以使用如下方式定义一个不定长数组:

struct flex_array* p_array = malloc(sizeof(struct flex_array) + sizeof(int) * count);
if (p_array != NULL) {
    p_array->count = count;
    // 使用柔性数组,如 p_array->data[0] = 42;
}

在使用柔性数组时,需要使用 malloc 函数同时为柔性数组和固定大小的结构体元素分配内存空间,计算内存大小时需要考虑柔性数组的元素个数。然后,可以通过指向结构体的指针进行柔性数组的访问和操作。

老师推荐值得一看的文章:
https://coolshell.cn/articles/11377.html

问:struct test t;结构体默认内部项目都是0吗?
ChatIAI答:
在C语言中,如果一个结构体变量没有被初始化,其中的每个成员变量的值是未定义的(也就是随机的)。如果你想要确保结构体中的所有成员都为0,可以使用以下方法:

  1. 在定义结构体变量时将其全部初始化,例如:
struct test t = {0};

这将把结构体中所有成员变量的值都初始化为0。

  1. 使用memset()函数将结构体变量的内存清零,例如:
struct test t;
memset(&t, 0, sizeof(struct test));

此方法将清除结构体变量的所有内存,并将其所有成员变量的值设置为0。

需要注意的是,对于复杂的结构体类型,如果其中包含指针成员变量等非基本数据类型,使用memset()将结构体变量的内存清零可能会导致内存泄漏或者指针变成野指针,因此需要特别注意。

特别注意以下代码:

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

struct test {
	int i;
	short c;
	char *p;
	char s[10];
};
int main() {
	struct test *pt = NULL;
	printf("&s = %x\n", pt->s); 
	printf("&i = %x\n", &pt->i); 
	printf("&c = %x\n", &pt->c);
	printf("&p = %x\n", &pt->p);
	return 0;
}

代码转自:https://coolshell.cn/articles/11377.html
问:为什么pt->s和&pt->s都可以,但是&pt->p和pt->p不一样?
ChatAI答:
在C语言中,结构体成员变量可以是基本数据类型(如int、short等)、数组或指针。对于基本数据类型和数组类型的结构体成员,它们的值都被存储在结构体的内存空间中。因此,使用&pt->i和&pt->s是等价的,它们都可以用来获取结构体成员变量i和s的内存地址。

但是对于指针类型的结构体成员变量p,它的值是一个地址,这个地址指向的是另外一块内存空间(指针所指向的内存空间)。因此,使用&pt->p可以获取指向指针变量p本身的内存地址,而不是指向p所指向的内存空间的地址。因此,pt->p和&pt->p不是等价的,它们分别表示指针变量p所指向的内存空间的地址和指针变量p本身的内存地址。如果要获取指针变量p所指向的内存空间的地址,应该使用pt->p而不是&pt->p。

问:在C语言中,为什么printf(1)报错,printf(0)不报错。
ChatAI答:
在C语言中,printf()是一个标准库函数,用于将字符串和其他数据输出到标准输出流中(通常是控制台或文件)。

当你调用printf(1)时,参数1将被视为一个整数类型的表达式。但是printf()要求第一个参数必须是格式化字符串(格式化字符串确定如何将后续参数格式化为字符串输出)。因此,编译器会报错并指出你的代码有语法错误。

当你调用printf(0)时,参数0将被视为一个NULL指针。虽然这种用法是合法的,但它不符合printf()的预期行为,因为printf()需要一个格式化字符串参数。因此,编译器不会报错,但程序可能不会按照你的期望输出任何东西。

在C语言中,函数的参数类型和数量必须与函数声明或定义一致,否则编译器会报告错误。因此,你应该使用printf()的正确格式来调用它,例如:

printf("%d", 1);

这将把1作为整数输出到控制台上。

自行摸索:

#define _CRT_SECURE_NO_WARNINGS 1

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

struct S
{
	int n;
	int* arr;
};

int main()
{
	struct S s = { 0 };
	struct S* p = &s;
	printf("%p\n", &s);
	printf("%p\n", &s.n);
	printf("%p\n", &s.arr);
	printf("%p\n", p);
	printf("%p\n", &p->n);
	printf("%p\n", &p->arr);
	p->arr = malloc(40);
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		p->arr[i] = i;//0 1 2 3 4
	}
	for (i = 0; i < 5; i++)
	{
		printf("%d ", p->arr[i]);
	}
	free(p->arr);
	p->arr = NULL;
	return 0;
}

输出:
在这里插入图片描述

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

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

相关文章

【C++学习】智能指针

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《C学习》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 智能指针 &#x1f96e;智能指针&#x1f362;为什么需要智能指针&#x1f362;RAII &#x1f96e;au…

chatgpt赋能python:Python自动开机:提高效率的必备工具

Python 自动开机&#xff1a;提高效率的必备工具 随着科技的发展&#xff0c;计算机在我们的日常生活中扮演了越来越重要的角色。为了提高工作效率和使用体验&#xff0c;越来越多的人开始探索利用自动化工具来简化日常操作。 Python 称得上是自动化领域中的一把利器。通过代…

SAP-MM费用类采购通过物料组确定科目

一、WRX的配置&#xff0c;分两类GR/IR科目&#xff1a; 1、做库存管理物料的GR/IR科目&#xff0c;需要配置评估类&#xff0c;此评估类就是物料主数据里配置的评估类&#xff1b; 2、非库存管理费用化物料的GR/IR科目&#xff0c;如固定资产、办公用品、低值易耗品等等&#…

chatgpt赋能python:Python生成C代码:如何用Python快速高效地生成C代码

Python生成C代码&#xff1a;如何用Python快速高效地生成C代码 在现代编程中&#xff0c;有许多原因需要编写C代码。C是一种高性能语言&#xff0c;它允许程序员直接操作计算机的硬件。但是&#xff0c;编写C代码需要花费大量的时间和精力。幸运的是&#xff0c;Python可以帮助…

Spring Boot问题汇总

1.IDEA里yaml文件编辑时没有提示 网上很多教程说在设置里的File Types里把yaml格式加入到关联中 但其实我打开IDEA默认就是这么设置的&#xff0c;所以并没有什么用处。 不过在翻看这篇教程&#xff08;IDEA创建yml文件不显示小树叶创建失败问题的解决方法-eolink官网&#x…

网络安全学习心得分享~

我的学习心得&#xff0c;我认为能不能自学成功的要素有两点。 第一点就是自身的问题&#xff0c;虽然想要转行学习安全的人很多&#xff0c;但是非常强烈的想要转行学好的人是小部分。而大部分人只是抱着试试的心态来学习安全&#xff0c;这是完全不可能的。 所以能不能学成并…

【Python】字符串操作

知识目录 一、写在前面✨二、字符串逆序三、打印菱形四、总结撒花&#x1f60a; 一、写在前面✨ 大家好&#xff01;我是初心&#xff0c;很高兴再次跟大家见面。&#xff08;相遇就是缘分啊&#xff09; 今天跟大家分享的文章是 Python中的字符串操作 &#xff0c;希望能帮助…

SAP-物料主数据-质量管理视图字段解析

过账到质检库存&#xff1a;要勾选&#xff0c;否则收货后库存不进入质检库存HU检验&#xff1a;收货到启用HU管理的库位时产生检验批&#xff0c;例如某个成品物料是收货到C002库位&#xff0c;该库位启用了HU管理&#xff0c;那么此处要勾选。但是如果勾选了&#xff0c;却收…

全网最全最有用的网络安全学习路线!整整一晚上才整理出来!

正文&#xff1a; 废话不多说&#xff0c;先上一张图镇楼&#xff0c;看看网络安全有哪些方向&#xff0c;它们之间有什么关系和区别&#xff0c;各自需要学习哪些东西。 在这个圈子技术门类中&#xff0c;工作岗位主要有以下三个方向&#xff1a; 安全研发安全研究&#xff1…

Linux-0.11 文件系统pipe.c详解

Linux-0.11 文件系统pipe.c详解 模块简介 在Linux-0.11中提供了管道这种进程间通讯的方式。本程序包含了管道文件读写操作函数read_pipe()和write_pipe()。 函数详解 read_pipe int read_pipe(struct m_inode * inode, char * buf, int count)该函数是读管道的方法。 函数…

python绘图工具matpoltlib的常用操作

目录 1.matplotlib概述2.风格设置3.条形图4.盒图5.直方图和散点图6.3D图7.pie图和布局8.Pandas与sklearn结合实例 1.matplotlib概述 Matplotlib 是一个用 Python 编程语言编写的、基于 NumPy 的开源数据可视化库。它提供了一套完整的兼容 MATLAB 的 API&#xff0c;支持各种常…

如何在华为OD机试中获得满分?Java实现【贪心的商人】一文详解!

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: Java华为OD机试真题&#xff08;2022&2023) 文章目录 1. 题目描述2. 输入描述3. 输出描述…

Unity之2D碰撞器

1、什么是碰撞器 碰撞器是用于在物理系统中 表示物体体积的的&#xff08;形状或范围&#xff09; 刚体通过得到碰撞器的范围信息进行计算 判断两个物体的范围是否接触 如果接触 刚体就会模拟力的效果产生速度和旋转 2、参数 Edit Collider&#xff1a;编辑碰撞器 Material…

chatgpt赋能python:Python校验和的介绍

Python 校验和的介绍 在计算机科学中&#xff0c;校验和是一种用于检测数据传输中错误的简单方法。它可以用来确保数据在传输过程中没有发生丢失、损坏或篡改。Python语言中&#xff0c;我们可以通过各种方法来计算校验和。 常用的校验和算法 Python中常见的校验和算法包括&…

chatgpt赋能python:Python绘图颜色

Python绘图颜色 Python是一种通用编程语言&#xff0c;也是数据科学和机器学习领域中最受欢迎的语言之一。Python的一个强大的功能是绘图&#xff0c;它可以用来呈现数据和信息的可视化。 在Python绘图中&#xff0c;颜色是一个非常重要的元素。颜色可以帮助我们更好地理解数…

英睿达内存条正品鉴别教程(镁光颗粒)

我们打算买一款二手镁光颗粒的英睿达内存条,需要从正面内存标签上的条形码、字串,从背面颗粒上的两行字符一一分析、检查、鉴别,最终确认是否正品,以及内存条等级如何。通过本片文章,您能学会如何进行镁光颗粒的英睿达内存条正品鉴别。 一、标签检查 首先,用百度条形码…

win11还原win10磁贴方法ExplorerPatcher,替代Start 11、StartALLBack(开源免费~)

文章目录 1.简介2.解决方案3.ExplorerPatcher3.1功能概要3.2软件安装3.3软件卸载 4.操作使用&#xff08;部分&#xff09;4.1磁贴开启4.2磁贴使用小技巧4.3优化建议4.4注意事项 5.下载地址 1.简介 微软&#xff1a;我不向前兼容&#xff0c;用户喷我兼容性差。我向前兼容&…

搭建自己的pts性能测试平台--jmeter+influxdb+chronograf+grafana

不知道大家有没有使用过阿里的性能工具pts&#xff0c;详细的数据视图不要太香&#xff0c;唯一的缺点就是收费。那有没有类似的这种平台&#xff0c;让我们可以不花钱就体验相同的快感呢&#xff0c;答案是有的&#xff0c;下图中的平台就是这片文章看完操作完之后&#xff0c…

【JAVA进阶】File类、字节流

&#x1f4c3;个人主页&#xff1a;个人主页 &#x1f525;系列专栏&#xff1a;JAVASE基础 前言&#xff1a; 目前的编程中&#xff0c;数据存储方式有很多种&#xff0c;包括但不限于&#xff1a; 文件存储&#xff1a;将数据以文件的形式存储在磁盘上&#xff0c;可以使用文…

Radxa ROCK 5A 开箱

Rock5 Model A 是一款高性能的单板计算机&#xff0c;它采用了 RK3588S (8nm LP 制程&#xff09;处理器&#xff0c;具有 4 个高达2.4GHz 的 ARM Cortex-A76 CPU 核心、4 个高达 1.8GHz 的 Cortex-A55 内核和 Mali-G610 MP4 GPU。更重要的是&#xff0c;它还有一个高达 6TOPS …