(C language) Dynamic memory allocation


1. Why does dynamic memory allocation exist?

Before we learned about dynamic memory, the memory allocation methods we knew were:

int i=20;//在栈空间上开辟四个字节
char arr[20]={
    
    0};//在栈空间上开辟10个字节的连续空间

The characteristics of the memory space allocated above are:
1. The size of the space allocated is fixed
2. When declaring the array, it must be specified The length of the array and the memory it requires are allocated during compilation
By observing these two ways of opening up memory, you will find that both methods have limitations and are not flexible enough, so we You must use dynamic memory allocation space
Note: The dynamic memory allocation space here is applied for in the heap area, not the stack area
Insert image description here

2. Dynamic memory function

1.malloc and free

malloc is a dynamic memory allocation function provided by C language:https://legacy.cplusplus.com/reference/cstdlib/malloc/?kw=malloc

  void* malloc (size_t size);

The function of this function is to allocate a continuous available space for an object of size bytes and return a pointer to this space. The initial value in this space is uncertain
If the allocation is successful, a pointer to the allocated space will be returned
If the allocation fails, a NULL pointer will be returned, so the return value of malloc must be checked
The type of the return value is void*, so the malloc function does not know the type of space to open. It is decided by the user when using it.
If the parameter size is 0, the behavior of malloc is undefined by the standard and depends on the compiler

In addition, C language also provides another function free, which is used to release and recycle dynamic memory
https://legacy.cplusplus.com/reference/cstdlib/free /?kw=free

void free (void* ptr);

The free function is used to release dynamically allocated memory
If the space pointed to by the parameter ptr is not dynamically allocated, the behavior of the free function is undefined
If the parameter ptr is a NULL pointer, the function will do nothing
Note: You must remember to release the dynamically allocated space and release it correctly. If you do not release it as required or do not release it, it will be a problem. Problems causing memory leaks
The use of malloc function and free function (as shown below)

#include <stdio.h>
#include <stdlib.h>//malloc和free所需要的头文件
int main()
{
    
    
    //申请一块空间来存放十个整型
	int* p =(int*) malloc(10 * sizeof(int));
	if (p == NULL)
	{
    
    
		perror("malloc");
		return;
	}
	int i = 0;
	for (i = 0; i < 10; i++)
	{
    
    
		*(p + i) = i;
	}
	for (i = 0; i < 10; i++)
	{
    
    
		printf("%d ", p[i]);
	}
	free(p);
	p = NULL;
	return 0;
}

Insert image description here

2.calloc

calloc is also a function provided by C language that can open up dynamic memory:
https://legacy.cplusplus.com/reference/cstdlib/calloc/?kw=calloc a>

void* calloc (size_t num, size_t size);

The function of this function is to open up a space for num elements of size and initialize each byte of the space to 0
The difference between calloc and malloc is that calloc will Initialize each byte of the requested space to all 0s before returning the address
Insert image description here
Use of calloc (as shown below)

#include <stdio.h>
#include <stdlib.h>
int main()
{
    
    
	int* p =(int*) calloc(10 , sizeof(int));
	if (p == NULL)
	{
    
    
		perror("calloc");
		return;
	}
	int i = 0;
	for (i = 0; i < 10; i++)
	{
    
    
		*(p + i) = i;
	}
	for (i = 0; i < 10; i++)
	{
    
    
		printf("%d ", p[i]);
	}
	free(p);
	p = NULL;
	return 0;
}

Insert image description here

3.realloc

The realloc function is to make dynamic memory management more flexible
Sometimes we will find that the space applied for in the past was too small, and sometimes we feel that the space applied for is too large. In order to be reasonable To apply for memory, we will make flexible adjustments to the memory size
The realloc function can adjust the dynamically allocated memory size
https://legacy .cplusplus.com/reference/cstdlib/realloc/?kw=realloc

void* realloc (void* ptr, size_t size);

ptr is the size of the memory to be adjusted
size is the new size of the memory after adjustment
The return value is the starting position of the memory after adjustment a>
On the basis of adjusting the size of the original memory space, this function will also move the data in the original memory to the new space
There are two situations when realloc adjusts the memory space. :
Case 1: There is enough space after the original space. Add space directly after the memory of the original space. The data in the original space remains unchanged
Insert image description here
Case 2 : There is not enough space after the original space. Find another continuous space of suitable size
on the heap space to use.
1. Copy the data in the old space to the new space
2. Release the old space
3. realloc returns the address of the new space
Insert image description here
realloc is used (as shown below)

#include <stdio.h>
#include <stdlib.h>
int main()
{
    
    
	int* p = (int*)calloc(10, sizeof(int));
	if (p == NULL)
	{
    
    
		perror("calloc");
		return;
	}
	int i = 0;
	for (i = 0; i < 10; i++)
	{
    
    
		*(p + i) = i;
	}
	for (i = 0; i < 10; i++)
	{
    
    
		printf("%d ", p[i]);
	}
	//空间不够,调整空间为10个整型
	int* ptr = (int*)realloc(p,10*sizeof(int));
	if (ptr == NULL)
	{
    
    
		p = ptr;
	}
	//使用


	//释放
	free(p);
	p = NULL;
	return 0;
}

3. Flexible array

In C99, the last element in a structure is allowed to be an array of unknown size. This is called a flexible array member.

1. Characteristics of flexible arrays

The flexible array member in the structure must be preceded by at least one other member
The size of the structure returned by sizeof does not include the memory of the flexible array
Contains The structure of the flexible array members uses the malloc() function for dynamic memory allocation, and the allocated memory should be larger than the size of the structure to accommodate the expected size of the flexible array

#include <stdio.h>
struct S
{
    
    
	char i;
	int a;
	int arr[];
};

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

Insert image description here

2. Use of flexible arrays

Code 1

#include <stdio.h>
struct S
{
    
    
	char c;//1
	//3
	int i;//4
	int arr[];//未知大小的数组 - 柔性数组成员
};

int main()
{
    
    
	struct S* ps = (struct S*)malloc(sizeof(struct S) + 20);
	if (ps == NULL)
	{
    
    
		perror("malloc");
		return 1;
	}
	ps->c = 'w';
	ps->i = 100;
	int i = 0;
	for (i = 0; i < 5; i++)
	{
    
    
		ps->arr[i] = i;
	}
	//打印
	for (i = 0; i < 5; i++)
	{
    
    
		printf("%d ", ps->arr[i]);
	}
	//空间不够了
	struct S* ptr = (struct S*)realloc(ps, sizeof(struct S)+40);
	if (ptr != NULL)
	{
    
    
		ps = ptr;
	}
	else
	{
    
    
		perror("realloc");
		return 1;
	}
	//增容成功后,继续使用
	
	//释放
	free(ps);
	ps = NULL;

	return 0;
}

Insert image description here
3. Advantages of flexible arrays

#include <stdio.h>
struct S
{
    
    
	char c;
	int i;
	int* data;
};

int main()
{
    
    
	struct S* ps = (struct S*)malloc(sizeof(struct S));
	if (ps == NULL)
	{
    
    
		perror("malloc1");
		return 1;
	}
	ps->c = 'w';
	ps->i = 100;
	ps->data = (int*)malloc(20);
	if (ps->data == NULL)
	{
    
    
		perror("malloc2");
		return 1;
	}
	int i = 0;
	for (i = 0; i < 5; i++)
	{
    
    
		ps->data[i] = i;
	}
	for (i = 0; i < 5; i++)
	{
    
    
		printf("%d ", ps->data[i]);
	}
	//空间不够了,增容
	int* ptr = (int*)realloc(ps->data, 40);
	if (ptr == NULL)
	{
    
    
		perror("realloc");
		return 1;
	}
	else
	{
    
    
		ps->data = ptr;
	}
	//增容成功就使用
	//...
	//释放
	free(ps->data);
	ps->data = NULL;
	free(ps);
	ps = NULL;

	return 0;
}

The above code can achieve the same function as code 1, but the implementation of code 1 is better than the above code:
1. Convenient memory release< a i=2> If our code is in a function used by others, you make a secondary memory allocation in it and return the entire structure to the user. The user can release the structure by calling free, but the user does not know that the members in the structure also need to be free, so you cannot expect the user to discover this. Therefore, if we allocate the memory of the structure and the memory required by its members at once, and return a structure pointer to the user, the user can release all the memory once free 2. It is beneficial to improve the access speed Continuous memory is beneficial to improve the access speed and also beneficial to reduce memory fragmentation


Guess you like

Origin blog.csdn.net/2301_78373304/article/details/133809852