(本质上是值传递)
发布时间:2025-06-24 20:19:53 作者:北方职教升学中心 阅读量:516
一. malloc 和 free
1. malloc
void* malloc(size_t size);
解释:在堆区中开辟一块大小为 size 个字节的空间,返回指向这块空间的起始地址(泛型指针void*)。
二. calloc
void* calloc(size_t num, size_t size);
解释:在堆区中开辟一块大小为num * size个字节的空间,返回指向这块空间的起始地址,其中 num 为数据的个数,size 为单个数据的字节数,同时把申请的空间的每个字节初始化为全为0。所以说C语言并不是这么冷若冰霜的。这是一个好习惯。
以上内容是指针入门级别,先熟知,之后内容包括,指针类型的意义,指针解引用的权重,指针运算。(本质上是值传递)。若重新开辟一个新的数组会消耗大量的内存,所以传递的不是数组而是地址!
2.一维数组传参的本质:
#include <stdio.h>void test(int arr[])//重点{ int sz2 = sizeof(arr) / sizeof(arr[0]); printf("sz2 = %d\n", sz2);}int main(){ int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int sz1 = sizeof(arr) / sizeof(arr[0]); printf("sz1 = %d\n", sz1); test(arr);//重点 return 0;}
我们发现在函数内部是没有正确获得数组的元素个数,这又是为什么呢?你也许会想,指针怎么这么…(此处省略一万字),要尝试先接受它,以后学习多了自然都解释地清了。
因为这块空间存放的数据类型不知(由程序员自己确定),所以用泛型指针接收该地址,在使用的时候记得养成一个好习惯:
强制类型转换为自己需要的数据类型。202、指针变量和解引用操作符(*)
2.2.2 指针类型的拆分
2.2.3 解引用操作符
2.2.4指针变量的大小
小知识:typedef重命名:
3.动态内存管理
一. malloc 和 free
1. malloc
2. free
二. calloc
三. realloc
情况1:
情况2:
编辑情况3:
4.结构体
一.结构体
1.结构体的声明
2.结构体变量成员访问操作符
3.结构体传参
4.匿名结构体
5.结构的自引用
结尾祝福语
一、
realloc函数也能开辟空间,代码如下:
#include<stdio.h>#include<stdlib.h>int main(){ int* p = (int*)realloc(NULL, 10 * sizeof(int));//等价于malloc(40) if (p == NULL) { //... } return 0;}
4.结构体
如果我写的不明白,查看对标链接,感谢各位支持!!!!!!
自定义类型:结构体+结构体内存对齐+结构体实现位段_自定义结构体位对齐如何查询-CSDN博客自定义类型:结构体+结构体内存对齐+结构体实现位段_自定义结构体位对齐如何查询-CSDN博客自定义类型:结构体+结构体内存对齐+结构体实现位段_自定义结构体位对齐如何查询-CSDN博客
前言:
学习了数组后发现数组中的元素只能是相同类型的变量,那么有没有可以存放不同类型的变量呢?
结构体:一些值的集合,这些值称为成员变量,结构体的每个成员可以是不同类型的变量。。
int arr2[6] = {1};//不完全初始化第⼀个元素初始化为1,剩余的元素默认初始化为0
int arr3[3] = {1, 2, 3, 4};//错误的初始化 初始化项太多 【违法越界】
int arr4[] = {};//错误的写法【初始化和元素数必须要有一个!!!!不然编译器无法识别】
int arr5[] = ;//特殊初始化//通过初始化的个数,判断元素的个数,只有1个元素
int arr6[] = {1,2,3};//特殊初始化//有3个元素
char arr7[]="abc";//字符数组初始化//字符数组【字符串定义数组】
2.字符数组的初始化
下面就是的3种书写方式:
// char ch[9] = ;//不完全初始化
// char ch2[9] = { 'a','b','c'};//各字符初始化
// char ch3[9] = "abc";//字符串初始化
不管如何,字符初始化的就这三种方式,接下来我们来重点看一下两种初始化的对比({ 'a','b','c'}和"abc"):
探索方法:F10进入分布调试页面,F11分步调节,在监视页面,输入数组名,观看其储存形式。
1.2一维数组的初始化
1.整型数组的初始化
首先先来说数组的一种初始化,也是最常用的初始化:
指在创建的基础上给一个或多个合理的值;而每个类型的初始化又存在差异,
本章的初始化我们就来讨论其差异性,这里没啥大用,做了解即可,看我慢慢给你解释!!!!
数组分为完全初始化和不完全初始化
先来看一个不完全初始化:

解释:arr与[10]结合,说明我们定义了一个空间为10个的数组,int表示空间的每个元素是为整型;
{1}在这里是什么意思?为什么定义了十个空间,这里只有一个元素?
这里叫做不完全初始化,后面给的初始化元素数少于定义的元素数, 后面的元素要我们在后续的程序中自己定义。
如图:
二、
思考:以下代码行不行struct{ int age; char name[50]; float height;}s1;struct{ int age; char name[50]; float height;}*ps;int main(){ ps = &s1;//? return 0;}
struct{ int age; char name[50]; float height;}s1;struct{ int age; char name[50]; float height;}*ps;int main(){ ps = &s1;//? return 0;}
答案:不行,看似一样,其实这两个结构体是不同类型的,只是成员变量相同的不同结构体类型,二者不兼容。。
为什么捏???
先直观的感受一下指针变量的大小的运作结果:
printf("%d\n", sizeof(char*)); printf("%d\n", sizeof(int*)); printf("%d\n", sizeof(double*)); printf("%d\n", sizeof(short*)); printf("%d\n", sizeof(float*));
我们看一下32位(x86)的平台下运行的结果
结果显示:在x86的平台下运行的结果,无论什么类型都是4个字节。 总结:⼀维数组传参,形参的部分可以写成数组的形式,也可以写成指针的形式。 如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。 对!!!,这么大个单元楼,怎么多房间,要怎么分辨小雪的房间哪? 所以我们给这里的每一个内存单元(房间)编制了房间号, 一楼:101、 //匿名结构体类型 typedef重命名函数 比如我们命名了一个结构体叫做jinfsjajngijiasogjoiasjda(随便打的) 我们每次调用都要写很长一段复杂的东西,但是有了typedef这个东西,我们可以将它重命名为js,对!就这两个字符,就可以表达这个结构体 typedefunsigned int uint; //将unsigned int重命名为uint 如果是指针类型,能否重命名呢?其实也是可以的,比如,将 int* 重命名为 ptr_t,这样写: typedefint*ptr_t; 但是对于数组指针和函数指针稍微有点区别: typedefint(*parr_t)[5]; 函数指针类型的重命名也是⼀样的,比如,将 void(*)(int) 类型重命名为 pf_t ,就可以这样写: 那么要简化代码2,可以这样写: 重点 给出typedef命名一个数组的例子: 前言: 当我们要开辟一块连续的内存空间时,我们第一时间想到的可能是数组。指针变量和解引用操作符(*) 当我们用去地址操作符取出地址时如:0x006FFD69,那么我们将这个东西存在哪里哪? 答案是指针变量!!!! 例子: 举个例子: int a=10; int *p=&a; 我们已经知道 对的,解引用操作符也是我们的 老 朋 友 * 号 int a=10; int *p=&a;//指针变量存放a的地址 *p=10;//解引用操作将p所指向的对象的值改为10 先说结论 指针变量的大小只有两个值:4和8; !在32位的平台上运作时,指针变量的大小为4。 思考:我们发现二者都可以成功访问结构体成员,那二者有什么区别呢? 再看一下64位的(x64)的平台下运行的结果 : 结果显示:都是8个字节 简单来说:
4.匿名结构体struct//不完全声明,由于没有名字,无法在其之后创建变量{ int age; char name[50]; float height;}s1, s2;//在结构体声明的时候直接创建变量,不能在其之后创建变量了,只能使用一次int main(){ struct s3;//error}
当只需使用一次可以使用(在声明结构体时,直接创建变量,不能在其之后创建变量了)。 小知识:typedef重命名:
typedef是用来重命名的,可以将复杂的名字简单化,规范化
比如我们有数组指针类型 int(*)[5] ,需要重命名为 parr_t ,那可以这样写:typedef void(*pfun_t)(int);//新的类型名必须在*的右边
typedef void(*pfun_t)(int);pfun_t signal(int, pfun_t);
#include<stdio.h>int main(){typedef int IntArray[5]//定义一个包含5个int类型元素的数组类型IntArrayIntArray arr={1,2,3,4,5};// 使用 IntArray 声明一个数组 for(int i=0;i<5;i++){printf("%d",arr[i]); }return 0;}
3.动态内存管理
2.1指针变量
#include<stdio.h>int main(){int a=0;int*p=&a;//讲取出的a的地址存放到指针变量p中return 0;}
2.2 指针类型的拆分
2.3 解引用操作符
2.4指针变量的大小
#include <stdio.h>struct Person{ int age; char name[50]; float height;};void test1(struct Person p)//用结构体接收{ printf("%d %s %.1fn", p.age, p.name, p.height);}void test2(struct Person* p)//用结构体指针接收{ printf("%d %s %.1fn", p->age, p->name, p->height);}int main(){ struct Person p1 = { 20,"zhangsan",185.5 }; test1(p1);//传结构体 test2(&p1);//传结构体的地址 return 0;}
三楼:.......................
说回正题:
内存相比大家都不陌生,在你买电脑的时候总会了解到电脑是多少g内存的,如4G/8G/16G/32G而这些到底是怎么划分的哪????
其实,内存不是单独的一个大整体,而是一个大的空间被划分为一个一个的小空间,我们把它叫做内存单元,
每个内存单元都是1个字节。
5.结构的自引用
比如:定义一个链表的节点
struct Node{ int data;//存放数据 struct Node* next;//存放指针};
结尾祝福语
以上就是数据结构可能有用到的知识点,如果有人能看到这,我真感动呀!!!!!!,累死我了!!!!我知道你对我的文章是非常认可的,当然如果有错误,欢迎随时来指出,我们一起探讨,如果有疑问,直接私信我即可,看到的第一时间我会给你解答!!!!!!!也请各位给我个三连(点赞收藏评论!!!)
怎么说哪?结束了,第一次写万字文章,肯定有写的不好的地方,多多见谅吧!!!!最后祝你们四级全过,天天开心!!!!!!