第⼗篇,数组初始化和堆空间申请释放,以及结构体,联合体的定义,计算内存⼤⼩以及枚举类型的详细说明。
⼀、数组清零⽅式。
1、定义数组同时初始化0。
char A[10] = {0}; ---> 剩余没有赋值的成员都会赋值为0
缺点:在程序中只能定义⼀次数组,清零只是只有⼀次。
2、清空某段内存空间的数据。 ---> bzero() --> man 3 bzero
功能: bzero - write zero-valued bytes
//写⼊⼀些零值到内存空间上
#include <strings.h>
void bzero(void *s, size_t n);
参数:
s:需要清空的内存空间的地址
n:清空的长度
返回值:⽆
特点:多次调⽤,多次清零。
#include <stdio.h>
#include <strings.h>
int main(int argc,char *argv[])
{
char A[10] = {"hello"};
A[8] = 'k';
A[9] = 'l';
int i;
for(i=0;i<10;i++)
{
printf("A[%d]:%c\n",i,A[i]);
}
bzero(A,sizeof(A));
定义数组初始化for(i=0;i<10;i++)
{
printf("A[%d]:%c\n",i,A[i]);
}
return 0;
}
⼆、堆区空间的申请与释放。
1、堆区空间的特点?
堆空间,不像栈区那样通过申请变量⽽得到栈区空间,⽽是通过写代码调⽤malloc()函数去申请得到。
代码定义了局部变量 --> 等价于在栈区申请空间。
代码定义了全局变量 --> 等价于在bss段/data段申请空间。
代码定义"hello" --> 等价于在常量区申请空间。
代码出现malloc函数 --> 等价于在堆区申请空间。
堆区空间: 主动申请,主动释放。
注意:如果在⼀个函数中申请了堆区空间,请问在函数返回时,需要拿橡⽪擦出来吗?
不需要,因为堆区空间不会因为函数返回⽽释放。
2、如何申请堆区空间?
1)申请堆区空间 -- malloc() --> man 3 malloc
功能: allocate dynamic memory
申请堆区空间
头⽂件:
#include <stdlib.h>
函数原型:
void *malloc(size_t size);
参数:
size:需要申请堆区空间的字节数
返回值:
成功:堆区空间的起始地址 --> 由于这个地址是void*的,所以后⾯使⽤这个地址需要强制转换为某种类型才可以使⽤。 失败:NULL
2)释放堆区空间。 -- free() --> man 3 free
功能: free dynamic memory
释放堆区空间
头⽂件:
#include <stdlib.h>
函数原型:
void free(void *ptr);
参数:
ptr:需要释放的那段堆区空间的地址
返回值:⽆
⽤户在程序中必须主动释放堆区空间,如果不主动释放,那么在程序结束时,也会主动释放。
-------------------------------------------
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[])
{
int *p = malloc(8); //等价于在堆区申请了4个字节的空间
p[0] = 10;
p[1] = 20;
printf("p[0] = %d\n",p[0]); //p[0] = *(p+0) = *p
printf("p[1] = %d\n",p[1]);
free(p);
return 0;
}
-------------------------------------------
3、如果堆区空间释放之后,还能不能访问这段堆空间。
能,但是那⽚空间的数据有可能已经更改。
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[])
{
//申请空间: 该空间从不属于你变成属于你。
int *p = malloc(20);
p[0] = 10;
p[1] = 20;
p[2] = 30;
p[3] = 40;
p[4] = 50;
printf("p[0] = %d\n",p[0]);
printf("p[1] = %d\n",p[1]);
printf("p[2] = %d\n",p[2]);
printf("p[3] = %d\n",p[3]);
printf("p[4] = %d\n",p[4]);
/
/释放空间: 该空间从属于你变成不属于你。
free(p);
p = NULL; //以后写代码,为了安全起见,最好写上这句话,⽬的就是为了我们再次去访问该堆区空间。
printf("p[0] = %d\n",p[0]);
printf("p[1] = %d\n",p[1]);
printf("p[2] = %d\n",p[2]);
printf("p[3] = %d\n",p[3]);
printf("p[4] = %d\n",p[4]);
return 0;
}
练习1: 在⼀个⾃定义函数中申请堆空间,测试看看函数返回时候,这个堆区空间还在不在。
#include <stdio.h>
#include <stdlib.h>
int *func(int x)
{
int *p = malloc(4);
p[0] = x;
return p;
}
int main(int argc,char *argv[])
{
int a = 100;
int *p = func(a);
printf("p[0] = %d\n",p[0]);
free(p);
p = NULL;
return 0;
}
三、关于堆栈的易错点。
问题:以下代码是否有问题?如果没有问题,请画出内存图并指出每句话是什么意思,如果有问题,请指出问题所在。
1、
char A[10] = "hello"; //在内存空间中连续申请10个字节的空间,然后使⽤变量A间接访问这⽚空间,然后将常量区中的"hello"字符串拷贝到这个变量A所代表的空间上
strcpy(A,"world"); //把常量区的"world"字符串拷贝到变量A所代表的空间。
2、
char *p = "hello";
strcpy(p,"world");
3、
char A[10];
char *p = A;
strcpy(p,"hello");
4、
char A[10];
char *p = A;
p = "hello";
5、
char *p = malloc(sizeof(char)*10);
p = "hello";
6、
char *p = malloc(sizeof(char)*10);
strcpy(p,"hello");
第5与第6的区别:
第5,⼀开始p是指向堆区,然后接下来p就指向常量区。
第6,⼀开始p是指向堆区,然后接下来p依然是指向堆区,但是把常量区hello这个字符串拷贝到p所指向的堆区空间。
四、结构体。
1、什么是结构体?
多个相同类型的变量放在⼀个集合中,那么这个集合叫做数组。 --> int A[5] --> 5个int类型的数据
多个不同类型的变量放在⼀个集合中,那么这个集合叫做结构体。
结构体中可以包含哪些类型的数据呢?
1)基本数据类型:char/short/int/long/float/double
2)⾮基本数据类型:数组/指针/结构体
结构体中不可以包含哪些类型的数据呢?
不可以在结构体中定义函数。
总结: 结构体可以理解为就是⼀种新的数据类型,这种新类型有什么东西组成的呢?⽽是由我们⽤户⾃定义的。
也就是说,你想这个结构体⾥⾯有什么东西组成,由你来决定。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论