Flexible array @ dynamic memory management

Keywords: C


🔑 Citation:

Perhaps you have never heard of the concept of flexible array, but it does exist.
In C99, the last element in the structure is allowed to be an array of unknown size, which is called a "flexible array" member.

To make the array size controllable, it is necessary to cooperate with dynamic memory development.

For example:

struct st_type
{
	int i;
	int a[0];//Unknown size -- but writing 0 is allowed
};

If some compilers report errors, change to:

struct st_type
{
	int i;
	int a[];//Unknown size
};

5.1 characteristics of flexible array

❄️ 1. The flexible array member in the structure must be preceded by at least one other member.
❄️ 2. The structure size returned by sizeof containing flexible array members does not contain flexible array memory (there is also memory alignment).

Code experience:

#include<stdio.h>

struct st_type
{
	int i;//4byte
	int a[];
};

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

Operation results:

❄️ 3. The structure containing flexible array members should use malloc for dynamic memory allocation, and the allocated memory should be larger than the size of the structure to adapt to the expected size of the flexible array.

The following describes the use of flexible arrays.

5.2 use of flexible arrays

❄️ Structures containing flexible array members should be used in conjunction with dynamic memory allocation functions such as malloc.


⛄ Dynamically apply for space for structures containing flexible array members:

struct st_type* ps = (struct st_type*)malloc(sizeof(struct st_type) + 10 *sizeof(int));

⛄ If the array space is not enough, you want to adjust it to 20 int s

struct st_type* ptr = (struct st_type*)realloc(ps ,sizeof(struct st_type) + 20 * sizeof(int));

Complete code experience on:

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

struct st_type
{
	int i;//4byte
	int a[];
};

int main()
{
	struct st_type* ps = (struct st_type*)malloc(sizeof(struct st_type) + 10 * sizeof(int));
	if (ps == NULL)
	{
		printf("%s\n", strerror(errno));
		return(-1);
	}
	//use
	ps->i = 100;
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		ps->a[i] = i;
	}
	//...

	//The array space is not enough. I hope to adjust it to 20 int s
	struct st_type* ptr = (struct st_type*)realloc(ps, sizeof(struct st_type) + 20 * sizeof(int));
	if (ptr == NULL)
	{
		printf("Expand space failed\n");
		return -1;
	}
	else
	{
		ps = ptr;
	}
	//release
	free(ps);
	ps = NULL;
	return 0;
}

5.3 advantages of flexible array

Then some students want to put St_ The type structure is designed like this, which can also be realized:

struct st_type
{
	int i;//4byte
	int* a;//4byte
};

Therefore, after transformation, the above code still has the same function:

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

struct st_type
{
	int i;//4byte
	int* a;//4byte
};

int main()
{
	struct st_type* ps = (struct st_type*)malloc(sizeof(struct st_type));
	ps->i = 100;

	ps->a= (int*)malloc(10 * sizeof(int));
	//use
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		ps->a[i] = i;
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d ", ps->a[i]);
	}
	//...

	//If the space pointed to by a is not enough, you want to adjust it to 20 ints
	int* ptr = (int*)realloc(ps->a, 20 * sizeof(int));
	if (ptr == NULL)
	{
		printf("Capacity expansion failed\n");
		return -1;
	}
	else
	{
		ps->a = ptr;
	}
	//use
	//...

	//Two releases - pay attention to the order
	free(ps->a);
	ps->a = NULL;
	free(ps);
	ps = NULL;
	return 0;
}

Running results of the middle episode:

😇 Compared with the two codes, although they both realize the same function, we can also see the advantages of flexible array:

⛄ 1. Easy memory release
Just release once; If the number of malloc is small, the possibility of dynamic memory allocation related errors will be reduced.
If our code is in a function for others, you make a secondary memory allocation in it and return the whole 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 free, so you can't expect the user to find it. Therefore, if we allocate the memory of the structure and the memory required by its members at one time and return a structure pointer to the user, the user can free all the memory once.
⛄ 2. Conducive to access speed
malloc times are many, resulting in more memory fragments and low memory space utilization.
Continuous memory is beneficial to improve access speed. (in fact, I personally don't think it's much higher. Anyway, you can't run. You need to add the offset to address it.)

I haven't had many interviews, which is also the reason why I took it out alone, but I still hope all my friends can understand it!
This concludes the contents related to dynamic memory development @ side general book

Posted by reto on Sun, 03 Oct 2021 11:14:56 -0700