Basic storage class and dynamic memory allocation, storage class dynamic memory
For more information, seeC Primer Plus (sixth edition)Book
Storage Class and Memory Distribution
A brief introduction is given to the storage class of the variable and its memory distribution. We will first use a table to understand some basic terms:
Terms |
Explanation |
Example |
Scope |
Describes the areas of identifiers that can be accessed in a program. |
Block scope, function scope, function prototype scope, and File Scope |
Link |
Private part of the Variable |
External links (globally visible), internal links (visible to a single file), and no links (visible within a block) |
Storage Period |
Describes the lifecycle of an object accessed by an identifier. |
Static storage period, thread storage period, automatic storage period, and dynamic distribution of Storage Period |
Translation Unit |
A source file contains multiple head files. It is used as a translation unit during compilation as a file. |
The header file is contained in the source code file. |
> Block refers to a pair of codes enclosed in curly brackets. After C99, the block can also be a loop statement + loop body (single statement ). Variables with block scopes can only be visible within the block. Before C99, variables can only be declared at the beginning of the block. No link.
> The function scope is only used for the goto tag. A tag first appears in the inner Block of the function, and its scope will extend directly to the entire function. No link.
> Function prototype scope: the scope of the parameter when the function prototype is declared. It is limited to the prototype. No link. Note: If the variable length array is declared in the prototype of an int fun function, int fun (int n, int m, int vla [n] [m]) should be declared in this way;
> File Scope: defined outside the function, from the definition point to the end of the file. Has internal and external links.
> External link: variables with external links are visible in all files of the program. For example, in main. c, an external link variable int var is defined. In lock. c, extern int x is used to declare and use.
> Internal link: variables with this link are only visible to this file. For example, when using static int var and var, you do not need to add a declaration like an external link variable.
> No link: variables that do not have a file scope are not linked.
> Static storage period: Life (in memory): the start time and end time of the program.
> Thread storage period: Life: from the beginning to the end of the thread.
> Automatic Storage Period: the lifecycle is block-based and disappears when the block is left.
> Dynamically allocate storage periods: managed by programmers.
The summary table is as follows:
Storage Type |
Storage Period |
Scope |
Link |
Declaration Method |
Automatic |
Automatic |
Block |
None |
In-block |
Static external link |
Static |
File (entire program) |
External |
In addition to all functions, you must use extern to declare it again before using it in another file. |
Static internal link |
Static |
File (single Translation Unit) |
Internal |
Outside all functions, use static Declaration |
Static without Link |
Static |
Block |
None |
Block, declared using static |
In addition, there are register variables, which are not discussed due to their low practicability.
In memory, static data (including constants) occupies one region, automatic data occupies another region, and dynamically allocated data occupies the Third Region (memory heap ).
Dynamic memory allocation functions malloc () and release functions free ()
Before the C99 standard release, we cannot use variables as the number of elements in the declared array. If we want to create an array with a custom length, we cannot use the method that originally defined a normal static array. So what should we do? At this time, we need to declare the dynamic array by dynamically allocating memory.
The malloc () function is prototype in the stdlib. h file. It returns a void pointer pointing to the first address of the allocated memory. The following Code assigns a dynamic array with 10 int elements and points the pointer ptr to the first element of the array.
int *ptr, n = 10;ptr = (int *)malloc( (size_t)n * sizeof(int) );
The memory size to be allocated should be filled in the brackets of malloc (), in bytes, And the type is size_t. To provide program portability, we use the sizeof () operator to obtain the bytes occupied by the int type variables of the current system. We recommend that you use forced type conversion to use a pointer to the void type.
However, what if the memory allocation fails? The malloc () function returns a pointer to NULL. If the program continues to use the memory after the memory allocation fails, the program ends abnormally. Therefore, after memory allocation, check whether the allocation is successful.
int *ptr, n = 10;ptr = (int *)malloc( (size_t)n * sizeof(int) );if(ptr == NULL) exit(EXIT_FAILURE);
Or:
int *ptr, n = 10;if( !( ptr = (int *)malloc( (size_t)n * sizeof(int)) ) ) exit(EXIT_FAILURE);
Is a good method.
We know that the memory allocated by malloc () has a storage period of dynamic allocation, and the variable life period is controlled by programmers. If the program is not released in time before it ends, it will still exist after it ends. Even worse, if all the pointers pointing to the first address of the block memory are destroyed during the program running, the block memory will never be correctly accessed and cannot be released, this will cause memory leakage. Memory leakage is serious, causing the system to stop running! Because there is no free memory space, you must release it if you do not need to use it again after the memory is allocated! Be cautious about changing the pointer to the dynamically allocated memory space! Release the dynamically allocated memory. We use the free () function.
free(ptr);
This line of code releases the memory space previously allocated with malloc.
Dynamic Array sorting instance 1 # include <stdio. h> 2 # include <stdlib. h> 3 # include <conio. h> 4 5 int main (int argc, char * argv []) {6 int * ptr; 7 int key, size, I, j; 8 9 printf ("Enter the dynamic array size:"); 10 while (! (Scanf ("% d", & size) | size <0) {11 printf ("incorrect input. Please enter it again. \ N: "); 12 while (getchar ()! = '\ N'); // adjust the input buffer 13} 14 15 if (! (Ptr = (int *) malloc (size_t) size * sizeof (int) {// allocate memory 16 printf ("Memory Request failed! "); 17 exit (EXIT_FAILURE); 18} 19 20 printf (" Please input the array element content in sequence: \ n "); 21 for (I = 0; I <size; I ++) 22 scanf ("% d", & ptr [I]); 23 while (getchar ()! = '\ N'); 24 25 for (I = 1; I <size; I ++) {// insert sort 26 j = I-1; 27 key = ptr [I]; 28 while (j> = 0 & ptr [j]> key) {29 ptr [j + 1] = ptr [j]; 30 j --; 31} 32 ptr [j + 1] = key; 33} 34 35 printf ("the output after sorting each element is as follows:"); 36 for (I = 0; I <size; I ++) 37 printf ("% d", ptr [I]); 38 39 free (ptr); // release the memory, top priorities: 40 41 _ getch (); 42 return 0; 43}Dynamic Array sorting instance
Running result:
Supplement: realloc () function
Prototype: void * realloc (void * ptr, size_t size );
Simple Description: Change the memory space pointed to by ptr to size bytes, and the content of the memory block in size bytes remains unchanged. This function returns the position of the block. If the space cannot be reassigned, NULL is returned. If ptr is NULL, its behavior is the same as calling the malloc () with the size parameter. If the size is 0 and ptr is not NULL, its behavior is the same as the free call with the ptr parameter.
It is not recommended to use this function in large quantities, because when the space cannot be re-allocated, the function returns NULL, the original allocated memory block address is lost, causing memory leakage. Although this function is very convenient in many cases. If you need to use this function, save the address of the original memory block first!