C语言动态内存分配及其函数

目录

一,为什么用动态内存分配

二.malloc函数

(1)malloc函数介绍

(2)注意事项

三.calloc函数

四.realloc函数

(1)realloc函数介绍

(2)注意事项


一,为什么用动态内存分配

在C语言中,我想要创建一个个可变长度的的数组, 那我该怎么做呢?

试着创建一个可变大小的结构体数组。

代码:

struct S {
	char name[20];
	int age;
};

int main() {
	int n = 0;
	scanf("%d", &n);
	struct S arr[n];
	return 0
}

 结果VS编译器报了错误

这难道是编译器的问题? 

在linux环境下我继续尝试了上面的代码

 

 代码运行成功了!!

这是为什么呢?

原来C语言C99标准中增加了 linux支持,在linux是可以创建变长数组(数组长度可变的).

如果我们一定要在VS中使用可变数组呢?那么得用使用动态内存分配函数了!!

二.malloc函数

(1)malloc函数介绍

malloc的参数是一个int类型,指的是所需开辟内存的字节大小

malloc会返回一个指向开辟空间的指针.如果开辟失败,会返回空指针

malloc的返回类型是void*,返回的是内存起始地址

举例:

使用malloc函数向内存申请10个整形的空间,

    #include<stdilb.h>

    #include<string.h>

    #include<errno.h>

    int* p=(int*) malloc(10*sizeof(int));
    if (p==NULL)
    {
        printf("%s\n", strerror(errno));
    }

由于malloc函数返回值是void*,如果是需要一个整形指针接收,要使用(int*)进行强制类型转换,

如果开辟失败,则打印出出错信息,

如果开辟成功,则创建这个内存,p指针指向了这段内存的起始地址

画画图:

内存布局:

可以看到,生成的都是cd cd的内存地址

 

用这段内存打印出0-9:


int main() {
	int* p=(int*) malloc(10*sizeof(int));
	if (p==NULL)
	{
		printf("%s\n", strerror(errno));
	}
	else
	{
		int i = 0;
		for (i = 0; i < 10; i++)
		{
			*(p + i) = i;
		}
		for (i = 0; i < 10; i++)
		{
			printf("%d ", *(p + i));
		}
		*(p + 1) = 1;
	}

	free(p);

	return 0;
}

妥妥的打印了出来 

 

(2)注意事项

1.开辟的内存不能超过最大空间,否则会返回空指针!

试下开辟INT_MAX个字节的空间, 这个数字是几十亿级的

尝试下,结果是失败的,报错信息是空间不够足

 说明开辟空间时,内存需要足够的大,而且判断是否开辟成功能让代码变的更加的安全!!

2. 当动态申请的空间不再使用的时候,应该还给操作系统

也就是在使用完内存后,需要用free函数,释放出去.

三.calloc函数

(1)calloc函数介绍

calloc的第一个参数是元素的个数,第二个参数是每个元素的长度

calloc开辟空间,但是各个字节初始化都是0

calloc会返回一个指向开辟空间的指针.如果开辟失败,会返回空指针

calloc的返回类型是void* ,返回的是内存起始地址

举例:

使用calloc函数向内存申请10个整形的空间.并打印出存放的元素.

    #include<stdilb.h>

    #include<string.h>

    #include<errno.h>

    int* p = (int*)calloc(10, sizeof(int));
    if (p==NULL)
    {
        printf("%s\n", strerror(errno));
    }
    else
    {
        int i = 0;
        for ( i = 0; i < 10; i++)
        {
            printf("%d ", *(p + i));
        }
    }

 可以看到,打印出的都是0

内存布局: 

 

 

四.realloc函数

(1)realloc函数介绍

调整动态开辟内存空间的大小

第一个参数是开辟内存对应的指针,第一个参数是添加需要调整的大小

举例:

我需要用内存分配打印出0-9的数字,而我只开辟了20字节的大小的空间

    int *p=(int*)malloc(20);
    if (p==NULL)
    {
        printf("%s\n", strerror(errno));
    }
    else
    {

        int i = 0;
        for ( i = 0; i < 5; i++)
        {
            *(p + i) = i;
        }
    }

假设这里,20个字节不能满足我们的使用了,希望我们能够有40个字节的空间,这里就可以使用realloc来调整动态开辟的空间

打印出来,后面五个为随机值

 

 

我们用realloc调整空间

    p = realloc(p, 40);

    if (p != NULL)
    {
        int i = 0;
        for (i = 5; i < 10; i++)
        {
            *(p + i) = i;
        }
        for (i = 0; i < 10; i++)
        {
            printf("%d ", *(p + i));
        }
    }

打印出来

(2)注意事项

1.如果p指向空间之后有足够的内存空间可以追加,则直接追加,后返回p

 比如,我们要开辟了这个20个字节的空间

开辟成功后地址是0x00945f68

可以看到,调整内存大小后,地址还是0x00945f68,则说明realloc返回的还是p原来的地址

2.如果p指向的空间之后没有足够的内存空间可以追加,则realloc函数会重新找一个新的内存区开辟一块满足需求的空间,并且把原来内存中的数据拷贝回来,释放旧的内存空间,返回新开辟空间的内存地址.

 00c55f68

 继续开辟20个字节的空间,不过这块空间准备调整成4000个字节

 执行后,可以看到内存地址已经发生了变化!!这说明函数已经开辟了另一块空间,指针p指向了该空间

 可以看到,原来的数据是没有发生变化的

3.得用新的变量来接收realloc函数的返回值,以免p被丢弃

    int* ptr = realloc(p, 4000);

	if (ptr != NULL)
	{
		p = ptr;
		int i = 0;
		for (i = 5; i < 10; i++)
		{
			*(p + i) = i;
		}
		for (i = 0; i < 10; i++)
		{
			printf("%d ", *(p + i));
		}
	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值