catalogue
2. Basic classification of types
3. Shaping the storage in memory
4. Storage of floating point in memory
7. Pointer and array written test questions
4, Character function and string function
8. Simulate the above memory function and string function
5, Custom types: structure, enumeration, union
1. Why is there dynamic memory allocation
2. Introduction to dynamic memory functions
1, Write in front
To tell the truth, I was really terrified that the basic article I wrote last could be on the hot search list 1 of the whole station. I felt that I didn't deserve this list 1. In fact, the sharing content was not so good. I was a little happy to be recognized by the friends of station C, which will further urge me to improve my level, improve the quality of my blog and be recognized by everyone. Before learning this article, you can learn from my last blog, which is conducive to a better understanding and learning of this article. Click the title to jump to the corresponding blog post.
The last one is about the foundation. This one is about the high-level version, which needs more practice and speculation. This article is a summary of learning C language before. The production is mainly for my review. Since it is knowledge, of course, sharing is very important. It is still the old saying. If you think this blog is good, please comment, collect and praise, Your Sanlian is my biggest production power. This article is about 30000 words. I don't have time to read it. I can collect it and take time to read it. Some of the contents are displayed in the form of links. I don't say much nonsense. Let's learn it!!!
2, Data storage
1. Introduction to data types
char //Character data type short //Short int //plastic long //Long integer long long //Longer shaping float //Single-precision floating-point double //Double precision floating point number
Meaning of type:
Use this type to open up the size of memory space (the size determines the scope of use).
How to view memory space.
2. Basic classification of types
Plastic family
char unsigned char signed char short unsigned short[int] signed short[int] int unsigned int signed int long unsigned long[int] signed long[int]
Floating point family
float double
Construction type
Array type Structure type struct Enumeration type enum Union type union
int main() { unsigned char a = 200; unsigned char b = 100; unsigned char c = 0; c = a + b; printf("%d %d", a + b, c); return 0; }
The execution result of the program is ()
A.300 300
B.44 44
C.300 44
D.44 300
Note: when printf passes in parameters, if it is an integer, four bytes will be passed in by default, so the result of a+b is received with a four byte integer and will not cross the boundary. c has discarded the highest 1 in the step of c = a+b, so it can only be 44 obtained from 300-256.
※ since printf is a function with variable parameters, the type of the following parameters is unknown, so no matter what type you pass in, printf will only be stored with two different lengths according to different types. Among them, only long, long, float and double are 8 bytes (note that float will be processed into double and then passed in), and other types are 4 bytes. Therefore, although the type of a + b is char, it is actually received with a four byte integer. In addition, during reading, 8 bytes are read in integer modes such as% lld and% llx and floating-point modes such as% f and% lf, and 4 bytes are read in others.
3. Shaping the storage in memory
Original code, inverse code, complement code
Original code
Directly translate binary into binary in the form of positive and negative numbers.
Inverse code
Keep the sign bits of the original code unchanged and reverse the other bits in turn.
Complement
Inverse + 1 gets the complement.
If you want to understand the calculation and binary of the original inverse complement, you can see my previous blog, binary explanation
About C language binary related content + written test exercises, it is recommended to collect
The statements of original code, inverse code and complement code are wrong ()
A. The original code of a number is that the number is directly converted into binary
B. Inverse code means that the binary symbol bits of the original code remain unchanged, and other bits are reversed bit by bit
C. The complement is the binary plus 1 of the inverse code
D. The highest bit of original code, inverse code and complement code is 0, which means negative number, and the highest bit is 1, which means positive number
ABC is correct, and D's description of sign bits is reversed
Storage of data in memory
#include<stdio.h> int main() { int a = 1; int b = -2; return 0; }
Data can be stored in memory in different sizes
The original, inverse and complement of positive numbers are the same.
For shaping: data is stored in memory, which actually stores complement.
Large and small end introduction
Large end (storage) mode means that the low bit of data is saved in the high address of memory, while the high bit of data is saved in the low address of memory;
Small end (storage) mode means that the low order of data is saved in the low address of memory, while the high order of data is saved in the high address of memory.
Why is there a big end and a small end
Why are there big and small end modes? This is because in the computer system, we take bytes as the unit, and each address unit corresponds to a byte, one byte is 8bit. However, in C language, in addition to the 8-bit char, there are also 16 bit short and 32-bit long (depending on the specific compiler). In addition, for processors with more than 8 bits, such as 16 bit or 32-bit processors, since the register width is greater than one byte, there must be a problem of arranging multiple bytes. Therefore, it leads to large end storage mode and small end storage mode. For example, for a 16bit short x, the address in memory is 0x0010, and the value of X is 0x1122, then 0X11 is the high byte and 0x22 is the low byte. For the big end mode, put 0X11 in the low address, that is, 0x0010, and 0x22 in the high address, that is, 0x0011. Small end mode, just the opposite. Our commonly used X86 structure is the small end mode, while KEIL C51 is the large end mode. Many arm and DSP are in small end mode. Some ARM processors can also be selected by hardware whether it is large end mode or small end mode.
unsigned int a = 0x1234; unsigned char b = *(unsigned char*)&a;
On a 32-bit large end mode processor, the variable b is equal to ()
In the large end sequence, the hexadecimal arrangement of four bytes from low address to high address is 00 00 12 34 respectively, and the content of the first byte is 00, so A is selected
The correct description of the byte order at the size end is ()
A. The big and small byte order refers to the binary bit order of data stored on the computer
B. The big and small byte order refers to the byte order of data stored on the computer
C. The big endian byte order stores the high byte content of data at the high address and the low byte content at the low address
D. The small end byte order is to store the high byte content of data at the low address, and the low byte content at the high address
Small end byte order: put the low order in the low address
Big endian byte order: put the high bit at the low address
The result of the following code is ()
int main() { char a[1000] = { 0 }; int i = 0; for (i = 0; i < 1000; i++) { a[i] = -1 - i; } printf("%d", strlen(a)); return 0; }
A is a character array. strlen finds the position where the trailing zero (i.e. the value is 0) appears for the first time. Considering that a[i] is actually a character type, if it is to be 0, the lower eight bits of - 1-i need to be all 0, that is, the problem is simplified to "find the value of I when the lower eight bits of - 1-i result are all 0 for the first time" (because the tail zero occurs for the first time when the subscript of the character array is I, the string length is I). If you only look at the lower eight bits, at this time, - 1 is equivalent to 255, so when i==255, all the lower eight bits of - 1-i (255-255) are 0, that is, when I is 255, a[i] is 0 for the first time, so the length of a[i] is 255
4. Storage of floating point in memory
Common floating point numbers:
3.14159 1E10 floating point number family includes: float, double and long double types. Range represented by floating point number: defined in float.h
for instance
int main() { int n = 9; float* pFloat = (float*)&n; printf("n The value of is:%d\n", n); printf("*pFloat The value of is:%f\n", *pFloat); *pFloat = 9.0; printf("num The value of is:%d\n", n); printf("*pFloat The value of is:%f\n", *pFloat); return 0; }
According to the international standard IEEE 754, any binary floating-point number V can be expressed in the following form:
(-1)^S * M * 2^E
(- 1)^s represents the sign bit. When s=0, V is a positive number; When s=1, V is negative.
M represents a significant number, greater than or equal to 1 and less than 2.
2^E represents the exponential bit.
For example: decimal 5.0, written in binary, is 101.0, equivalent to 1.01 × 2^2 . Then, according to the above V format, we can get s=0, M=1.01, E=2.
Decimal - 5.0, written as binary is - 101.0, equivalent to - 1.01 × 2^2 . Then, s=1, M=1.01, E=2.
IEEE 754 has some special provisions for the significant number M and index E.
E is not all 0 or all 1
At this time, the floating-point number is represented by the following rule, that is, subtract 127 (or 1023) from the calculated value of index E to obtain the real value, and then add the first 1 before the significant number M. For example, the binary form of 0.5 (1 / 2) is 0.1. Since it is specified that the positive part must be 1, that is, if the decimal point is shifted to the right by 1 digit, it will be 1.0 * 2 ^ (- 1). Its order code is - 1 + 127 = 126, which is expressed as 01111110, while the mantissa of 1.0 is 0 after removing the integer part and complementing 0 to 23 digits, then its binary representation is:
0 01111110 00000000000000000000000
E is all 0
At this time, the exponent E of the floating point number is equal to 1-127 (or 1-1023), which is the real value. The significant number M is no longer added with the first 1, but reduced to a decimal of 0.xxxxxx. This is done to represent ± 0 and small numbers close to 0.
E is all 1
At this time, if the significant digits M are all 0, it means ± infinity (the positive and negative depend on the sign bit s);
Explain the previous topic:
Next, let's return to the initial question: why does 0x00000009 revert to a floating point number and become 0.000000? First, split 0x00000009 to obtain the first sign bit s=0, the index E=00000000 in the following 8 bits, and the last 23 significant digits M = 000 million 1001.
9 -> 0000 0000 0000 0000 0000 0000 0000 1001
Since the index E is all 0, it conforms to the second case in the previous section. Therefore, the floating-point number V is written as: V=(-1)^0 × 0.00000000000000000001001 × 2^(-126)=1.001 × 2 ^ (- 146) obviously, V is a small positive number close to 0, so it is 0.000000 in decimal.
Let's look at the second part of the example. How to express floating point number 9.0 in binary? What is the decimal system? First, floating point number 9.0 equals binary 1001.0, i.e. 1.001 × 2^3.
9.0 -> 1001.0 ->(-1) ^ 01.0012 ^ 3->s = 0, M = 1.001, E = 3 + 127 = 130
Then, the sign bit of the first bit s=0, the significant number M is equal to 001, followed by 20 zeros to fill 23 bits, and the index E is equal to 3 + 127 = 130, i.E. 10000001. So, in binary form, it should be s+E+M, that is
0 10000010 001 0000 0000 0000 0000 0000
This 32-bit binary number, reduced to decimal, is 1091567616.
3, Advanced pointer
1. Character pointer
General use
int main() { char ch = 'w'; char* pc = &ch; *pc = 'w'; return 0; }
High order use
int main() { char* pstr = "hello bit."; printf("%s\n", pstr); return 0; }
Let's practice a problem
#include <stdio.h> int main() { char str1[] = "hello word."; char str2[] = "hello word."; char* str3 = "hello word."; char* str4 = "hello word."; if (str1 == str2) printf("str1 and str2 are same\n"); else printf("str1 and str2 are not same\n"); if (str3 == str4) printf("str3 and str4 are same\n"); else printf("str3 and str4 are not same\n"); return 0; }
Here, str3 and str4 point to the same constant string. C/C + + will store the constant string in a separate memory area when several pointers. When pointing to the same string, they actually point to the same block of memory. However, when initializing different arrays with the same constant string, different memory blocks will be opened up. So str1 and str2 are different, and str3 and str4 are different.
The following description of "pointer" is incorrect: ()
A. When a pointer content is released using free, the value of the pointer variable is set to NULL
B. The length of any type of pointer in 32-bit system is 4 bytes
C. The data type of the pointer declares the data type that the pointer actually points to the content
D. A wild pointer refers to an unallocated or released memory address
Afree does not change the point of the pointer.
The B option emphasizes the 32-bit system, so it's no problem.
The CD option is the definition itself.
So the exclusion method can also be determined to be A
The correct description of the following code is: ()
char* p = "hello word";
A. Store the string hello bit in the p variable
B. Store the first character of the string hello bit in the p variable
C. Store the address of the first character of the string hello bit in the p variable
D.*p is equivalent to hello bit
The paragraph enclosed in double quotation marks is a constant string. In essence, it is a constant character array type. Assigning it to a pointer is equivalent to assigning the first address of an array to the pointer, that is, the address of the first element h.
Only option C refers to the address of the first character, so select C
2. Pointer array
definition
Pointer array: a pointer that can point to an array.
int* p1[10]; int(*p2)[10]; //What are P1 and P2?
int (*p)[10]; //Explanation: P is first combined with * to indicate that P is a pointer variable, and then points to an array of 10 integers. So p is a Pointer, pointing to an array, called array pointer. //Note here that the priority of [] is higher than that of * sign, so () must be added to ensure that p is combined with * first.
&Array name VS array name
#include <stdio.h> int main() { int arr[10] = { 0 }; printf("%p\n", arr); printf("%p\n", &arr); return 0;
It can be seen that the address printed by the array name and & array name is the same.
#include <stdio.h> int main() { int arr[10] = { 0 }; printf("arr = %p\n", arr); printf("&arr= %p\n", &arr); printf("arr+1 = %p\n", arr + 1); printf("&arr+1= %p\n", &arr + 1); return 0; }
According to the above code, we find that although the values of & arr and arr are the same, they should have different meanings. In fact: & arr represents the address of the array, not the address of the first element of the array. (take a closer look) the address of the array is + 1, skipping the size of the entire array, so the difference between & arr + 1 and & arr is 40
Which of the following is an array pointer ()
A.int** arr[10]
B.int (*arr[10])
C.char *(*arr)[10]
D.char(*)arr[10]
A is the secondary pointer array, B is the pointer array, C is the pointer of char * array, and D is the array of char *. Only C is an array pointer.
tip: according to the priority, only option C is combined with * first, and others are not pointers, so select C directly.
Which of the following codes is wrong? ( )
#include <stdio.h> int main() { int* p = NULL; int arr[10] = { 0 }; return 0; }
A.p = arr;
B.int (*ptr)[10] = &arr;
C.p = &arr[0];
D.p = &arr;
In terms of data types, both left and right sides of A are int *, both left and right sides of B are int (*)[10], both left and right sides of C are int *, the left side of D is int *, and the right side is int (*)[10], so D is selected.
The incorrect description of the array name in the following code is ()
int main() { int arr[10] = {0}; return 0; }
A. The array names arr and & arr are the same
B.sizeof(arr), arr represents the entire array
C. & arr, arr represents the entire array
D. Except for the array name in sizeof(arr) and & arr, the array name arr in other places is the address of the first element of the array
The A option is obviously wrong. The type of arr is int [10], while the type of & arr is int (*)[10], which is not A type at all and cannot be the same. In sizeof(arr) and & arr, arr is regarded as A whole, and generally it represents the first address of an array.
3. Use of array pointer
#include <stdio.h> int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,0 }; int(*p)[10] = &arr;//Assign the address of array arr to array pointer variable p //But we rarely write code like this return 0; }
Use of an array pointer
#include <stdio.h> void print_arr1(int arr[3][5], int row, int col) { int i, j; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { printf("%d ", arr[i][j]); } printf("\n"); } } void print_arr2(int(*arr)[5], int row, int col) { int i, j; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { printf("%d ", arr[i][j]); } printf("\n"); } } int main() { int arr[3][5] = { 1,2,3,4,5,6,7,8,9,10 }; print_arr1(arr, 3, 5); //The array name arr represents the address of the first element //But the first element of the two-dimensional array is the first row of the two-dimensional array //So the arr passed here is actually equivalent to the address of the first row, which is the address of a one-dimensional array //You can use array pointers to receive print_arr2(arr, 3, 5); return 0; }
4. Function pointer
#include <stdio.h> void test() { printf("hehe\n"); } int main() { printf("%p\n", test); printf("%p\n", &test); return 0; }
Pfun1 can be stored. Pfun1 is first combined with * to explain that pfun1 is a pointer, the pointer points to a function, the pointed function has no parameters, and the return value type is void.
5. Function pointer array
To store the address of a function in an array, this array is called a function pointer array. How to define the array of function pointers?
int (*parr1[10]])(); int* parr2[10](); int (*)() parr3[10];
parr1 parr1 is first combined with [], indicating that parr1 is an array. What is the content of the array? Is a function pointer of type int (*) ()
Which of the following is a function pointer? ( )
A.int* fun(int a, int b);
B.int(*)fun(int a, int b);
C.int (*fun)(int a, int b);
D.(int *)fun(int a, int n);
There is no difference between ABD and parentheses. They do not affect any priority. They are all functions with a return value of int *, so choose C.
Define a function pointer. The pointed function has two int parameters and returns a function pointer. The returned pointer points to a function with one int parameter and returns int? Which of the following is true? ( )
A.int (*(*F)(int, int))(int)
B.int (*F)(int, int)
C.int (*(*F)(int, int))
D.*(*F)(int, int)(int)
If type D is incomplete, exclude it first, and then look at the return value. The return value of B is int, and the return value of C is int *, so select A. To judge the return value type, you only need to delete the function name / function pointer and parameter list and look at it again. int (*(*F)(int, int))(int) delete (* F)(int, int) and leave int (*)(int), which is consistent with the meaning of the question
In game design, different functions are often called according to different game states. We can achieve this function through function pointers. Which of the following is: a function pointer () with parameter int * and return value int
A.int (*fun)(int)
B.int (*fun)(int *)
C.int* fun(int *)
D.int* (*fun)(int *)
First, the root of C is not A function pointer. Exclude it first, then the return value of D is not int, exclude it, the parameter of A is not int *, exclude it, and B is left.
Declare a pointer to an array containing 10 elements, where each element is a function pointer. The return value of the function is int, the parameter is int *, and the correct is ()
A.(int *p[10])(int*)
B.int [10]*p(int *)
C.int (*(*p)[10])(int *)
D.int ((int *)[10])*p
A option, the first bracket is a complete definition, and the second bracket is a type, which is different. BD option, [] can only be on the right side of the identifier, and both are excluded. Only C can make it up.
6. Callback function
A callback function is a function called through a function pointer. If you pass the pointer (address) of a function as a parameter to another function, when the pointer is used to call the function it points to, we say it is a callback function. The callback function is not called directly by the implementer of the function, but by another party when a specific event or condition occurs, which is used to respond to the event or condition.
#include <stdio.h> //The user of the qosrt function has to implement a comparison function int int_cmp(const void* p1, const void* p2) { return (*(int*)p1 - *(int*)p2); } int main() { int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 }; int i = 0; qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), int_cmp); for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) { printf("%d ", arr[i]); } printf("\n"); return 0; }
7. Pointer and array written test questions
One dimensional array
int main() { int a[] = { 1,2,3,4 }; printf("%d\n", sizeof(a)); //The array name a is placed separately in sizeof. The array name represents the entire array and calculates the size of the entire array printf("%d\n", sizeof(a + 0)); //a represents the address of the first element. a+0 is also the address of the first element. The size of the address is 4 / 8 bytes printf("%d\n", sizeof(*a)); //A represents the address of the first element, * a is the first element = = > a [0], and the size is 4 //*a == *(a+0) == a[0] printf("%d\n", sizeof(a + 1)); //A represents the address of the first element, a+1 is the address of the second element, and the size is 4 / 8 printf("%d\n", sizeof(a[1])); //a[1] is the second element - 4 printf("%d\n", sizeof(&a)); //&A - address of array - 4/8 - int(*)[4] printf("%d\n", sizeof(*&a)); //*&A - & A is the address of the array. Dereferencing the address of the array gets the array, so the size is 16 //Equivalent to printf ("% d \ n", sizeof (a))// sixteen printf("%d\n", sizeof(&a + 1)); //4 / 8 & A is the address of the array, & A + 1 is the address of the array + 1, skipping the entire array, although skipping the array, //Or address 4 / 8 printf("%d\n", sizeof(&a[0])); //4/8 printf("%d\n", sizeof(&a[0] + 1)); //Address of the second element 4 / 8 return 0; }
Character array
char arr[] = { 'a','b','c','d','e','f' }; //There is no \ 0 in arr, but strlen() does not stop until it finds \ 0 printf("%d\n", strlen(arr)); //Find the length backward from the arr position (the address of the first element) and the random value printf("%d\n", strlen(arr + 0)); //Find the length backward from the arr position (the address of the first element) and the random value printf("%d\n", strlen(*arr)); //Arr is the address of the first element, * arr is the character 'a' - ascii-97. strlen counts the ASCII code value 97 corresponding to character a backward as the address. Illegal access! err printf("%d\n", strlen(arr[1])); //strlen counts backward the ascii code value 98 corresponding to character b as the address. Illegal access! err printf("%d\n", strlen(&arr));//&The address values of arr and arr are the same. They are the first element address, but their meanings are different //&Arr to strlen printf("%d\n", strlen(&arr + 1));//After skipping the entire array, count backward with a random value of - 6 //The memory space is continuous, and the \ 0 stop is found at the same time, but the random value obtained by strlen(arr) and strlen (& ARR) is 6 characters more than the second abcdef printf("%d\n", strlen(&arr[0] + 1));//Count backward from character b position, random number - 1
int main() { char arr[] = { 'a','b','c','d','e','f' }; //&Type of arr: array pointer: char(*)[6] printf("%d\n", sizeof(arr)); //The array list is placed in sizeof alone. It calculates the size of the entire array. The number of elements is 6 (excluding \ 0). The type is char, so the size is 6 printf("%d\n", sizeof(arr + 0)); //Arr here represents the first element address, arr+0 is still the first element address char *, and the address (pointer) size is 4 / 8 printf("%d\n", sizeof(*arr)); //Arr here represents the address of the first element, * arr is the first element of the array, that is, the character 'a' with a size of 1 printf("%d\n", sizeof(arr[1])); //Arr [1] - > character 'b', size 1 printf("%d\n", sizeof(&arr)); //Take out the address of the whole array, or the address. The size of the address is 4 / 8 printf("%d\n", sizeof(&arr + 1)); //Take the address of array arr + 1, skip an array, or the address. The size of the address is 4 / 8 printf("%d\n", sizeof(&arr[0] + 1));//Address of the second element of the array, 4 / 8 return 0; }
int main() { char arr[] = "abcdef"; //At this time, the array arr stores \ 0 strlen to find the length. When it encounters \ 0, it stops counting printf("%d\n", strlen(arr)); //Count backward from the arr position, stop when \ 0 is encountered, and the length is 6 printf("%d\n", strlen(arr + 0)); ///Count backward from the arr position, stop when \ 0 is encountered, and the length is 6 printf("%d\n", strlen(*arr));//Arr is the address of the first element, * arr is the character 'a' // The corresponding ascii value is 97. strlen counts backward the ascii code value 97 corresponding to character a as the address, err printf("%d\n", strlen(arr[1]));///arr[1]: the ascii value corresponding to 'b' is 98, //strlen counts backward the ascii code value 98 corresponding to character b as the address. Illegal access! err printf("%d\n", strlen(&arr)); //&The address values of arr and arr are the same. They are the first element address, but their meanings are different //&Arr is passed to strlen & arr type: array pointer char(*p)[6], while strlen receives char *, which is incompatible, but the problem is not big //Count backward from the position of the first element of the array, and the value is 6 printf("%d\n", strlen(&arr + 1)); //After skipping the entire array, count backward, unknown value printf("%d\n", strlen(&arr[0] + 1)); //Count backwards from b unknown, length 5 return 0; }
int main() { char arr[] = "abcdef"; //At this time, the arr array contains \ 0 printf("%d\n", sizeof(arr)); //The array list is placed in sizeof alone. The size of the entire array is calculated. 0 is also included. The size is 7 printf("%d\n", sizeof(arr + 0)); //At this time, the array name is the first element address, and the address (pointer) size is 4 / 8 printf("%d\n", sizeof(*arr)); //At this time, the array name is the address of the first element, * arr is the first element, the character a - > char type, and the size is 1 printf("%d\n", sizeof(arr[1])); //arr[1]: character 'b', size 1 printf("%d\n", sizeof(&arr)); //Get the address of the array, or the address, with a size of 4 / 8 printf("%d\n", sizeof(&arr + 1)); //Take out the address + 1 of the array, skip the whole array, or the address: 4 / 8 printf("%d\n", sizeof(&arr[0] + 1)); //Take the address of the first element + 1, skip one element, that is, the address of the second element, 4 / 8 return 0; }
#include<stdio.h> int main() { //&P [0] = = > is equivalent to & * (P + 0) - > is equivalent to sizeof (P). What is stored in P memory is the address of character a, + 1 is the address of character b, which is accessed backward from the position of character b, with a length of 5 // p[0]: character a //&P [0]: address of character a //&P [0] + 1: address of character b const char* p = "abcdef"; //p stores the address of the character a, //p+1: address of character b printf("%d\n", strlen(p)); //p stores the address of character a, that is, counting backward from the address of character a, with a length of 6 printf("%d\n", strlen(p + 1)); //Count backwards from the address of character b, with a length of 5 //printf("%d\n", strlen(*p)); //*P - > character 'a', i.e. counting backward with the ascii code value 97 of character a as the address, illegal access, err //printf("%d\n", strlen(p[0])); //P [0] - > character 'a', i.e. counting backward with the ascii code value 97 of character a as the address, illegal access, err printf("%d\n", strlen(&p)); //&p takes out the address of the p variable, that is, count backward with the address of the p variable (hexadecimal), and the random value printf("%d\n", strlen(&p + 1));//&p takes out the address of the p variable, & p + 1. Skip the p variable, that is, access the random value backward from the position after the p variable printf("%d\n", strlen(&p[0] + 1)); //&P [0] = = > is equivalent to & * (P + 0) - > is equivalent to sizeof (P). What is stored in P memory is the address of character a, + 1 is the address of character b, which is accessed backward from the position of character b, with a length of 5 return 0; }
int main() { //Because the pointer points to a constant string, it cannot be modified //So you can modify it with const //char* p = "abcdef"; const char* p = "abcdef"; //p stores the address of the character a printf("%d\n", sizeof(p)); //p is the pointer to the character a, with a size of 4 / 8 printf("%d\n", sizeof(p + 1)); //p+1, pointing to character b, pointer, size 4 / 8 printf("%d\n", sizeof(*p)); //p stores the address of character a, * p: it is character a, and the size is 1 printf("%d\n", sizeof(p[0])); //P [0] - > character a, size 1 printf("%d\n", sizeof(&p)); //Get the address of the p variable, which is still the address, with a size of 4 / 8 printf("%d\n", sizeof(&p + 1)); //Take the address + 1 of the p variable, skip the p variable, but still the address, and the size is 4 / 8 printf("%d\n", sizeof(&p[0] + 1)); //&P [0] is equivalent to & * (P + 0), & and * offset, & P [0]: the address of character a, + 1: the address of character b, with a size of 4 / 8 return 0; }
int main() { int a[3][4] = { 0 }; printf("%d\n", sizeof(a)); //The array list is placed inside sizeof, which calculates the size of the whole array, //There are 12 array elements, and the size of each element is 4 bytes, 12 * 4 = 48 printf("%d\n", sizeof(a[0][0])); //It calculates the size of the first element in the first row of the array, of type int, with a size of 4 printf("%d\n", sizeof(a[0])); //A [0] = = > * (a + 0) = = > the array name is the address of the first element, that is, the address of the first row. Dereference the address of the first row, // It is the first row, so the size of the elements in the first row is calculated as 4 * 4 = 16 //a[0]: first row of 2D array printf("%d\n", sizeof(a[0] + 1)); //a[0]: array name in the first row, representing the address of the first element in the first row, a[0]+1:: skip an element, // That is, the address of the second element in the first line, with a size of 4 / 8 //Note: a[0] + 1: not the second line, a[0] is the array name and first element address of the first line, //That is, the first element address of the first line, a[0]+1: skip an element, a+1: A is the array name, the first element address, the address of the first line, a+1, skip one line, and the second line of the two-dimensional array printf("%d\n", sizeof(*(a[0] + 1))); //From above, we can get: a[0]+1: the address of the second element in the first line, * (a[0]+1): that is, the second element in the first line. The int type size is 4 printf("%d\n", sizeof(a + 1)); //a is the array name - > address of the first element of the two-dimensional array, e is the address of the first row of the two-dimensional array, + 1, skip one row, that is, the address - > address of the second row, and the size is 4 / 8 printf("%d\n", sizeof(*(a + 1))); //From above, a+1 is the address of the second line, * (a+1) is the second line, and the size is 4 * 4 = 16 printf("%d\n", sizeof(&a[0] + 1)); //a[0] is the array name of the first row, &a[0] is the address of the first row, //(thus, the relationship between array name and address array name is the same, but they have different meanings), &a [0] + 1: skip the first line, that is, the address of the second line, address: 4 / 8 printf("%d\n", sizeof(*(&a[0] + 1))); //From above: (&a [0] + 1): the address of the second line. Dereference is the second line. The size is 4 * 4 = 16 printf("%d\n", sizeof(*a)); //The name of the two-dimensional array is the address of the first element, that is, the address of the first row. The dereference is the first row, and the size is 4 * 4 = 16 printf("%d\n", sizeof(a[3])); //a[3] if it exists, it is the array name in the fourth row. sizeof(a[3]) is equivalent to placing the array list inside sizeof alone. It calculates the size of the fourth row, 4 * 4 = 16 //The expression inside sizeof does not participate in the operation, that is, it will not really access the space of a[3], so there is no error. It only looks at the type of the fourth line, and does not really access the content of the fourth line, return 0; }
The result of the following procedure is: ()
int main() { int aa[2][5] = {10,9,8,7,6,5,4,3,2,1}; int *ptr1 = (int *)(&aa + 1); int *ptr2 = (int *)(*(aa + 1)); printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1)); return 0; }
&The type of AA is int (*)[2][5]. Adding one will lead to jump to the length of an int [2][5] and directly run to the position just beyond the boundary. After subtracting one, return to the last position 1* (aa + 1) is equivalent to aa[1], that is, the first address of the second line, which is naturally the position of 5. After subtracting one, due to the continuity of multidimensional array space, it will return to 6 at the end of the previous line
The result of the following procedure is: ()
int main() { int a[5] = {5, 4, 3, 2, 1}; int *ptr = (int *)(&a + 1); printf( "%d,%d", *(a + 1), *(ptr - 1)); return 0; }
* (a + 1) is equivalent to a[1], the first is 4, the type of a is int [5], the type of & A is int(*)[5], which is an array pointer. So adding one to the type int(*)[5] is equivalent to adding the length of an int [5]. That is, this pointer directly skips all the elements of a, directly refers to the position just beyond the boundary, and then converts it to int * and then minus one, which is equivalent to walking an int forward from that position, and returning to the address of 1 from the position just beyond the boundary, so the second is 1
4, Character function and string function
This section is explained in detail in my previous blog. Those who are interested can go to archaeology
1,strlen
size_t strlen ( const char * str );
The string has' \ 0 'as the end flag. The strlen function returns the number of characters before' \ 0 'in the string (excluding' \ 0 ').
The string pointed to by the parameter must end with '\ 0'.
Note that the return value of the function is size_t, which is unsigned (error prone)
2,strcpy
char* strcpy(char * destination, const char * source );
The source string must end with '\ 0'.
The '\ 0' in the source string will be copied to the destination space.
The destination space must be large enough to hold the source string.
The target space must be variable.
3,strcat
char * strcat ( char * destination, const char * source );
The source string must end with '\ 0'.
The target space must be large enough to accommodate the contents of the source string.
The target space must be modifiable.
4,strcmp
char * strcmp ( const char * str1, const char * str2)
If the first string is greater than the second string, a number greater than 0 is returned
If the first string is equal to the second string, 0 is returned
If the first string is less than the second string, a number less than 0 is returned
5,strstr
char * strstr ( const char *, const char * );
6,memcpy
void * memcpy ( void * destination, const void * source, size_t num );
The function memcpy copies num bytes of data back to the memory location of destination from the location of source.
This function will not stop when it encounters' \ 0 '.
If there is any overlap between source and destination, the copied result is undefined.
7,memmove
void * memmove ( void * destination, const void * source, size_t num );
The difference from memcpy is that the source memory block and target memory block processed by the memmove function can overlap.
If the source space and the target space overlap, memmove is used.
8. Simulate the above memory function and string function
memmove Enable overlapping and non overlapping copies void* my_memmove(void* dest, const void* src, size_t count)//unsigned int { //Front to back assert(dest && src); void* ret = dest; if (dest < src) { while (count--) { *(char*)dest = *(char*)src; dest = (char*)dest + 1; src = (char*)src + 1; } } //Back to front else { while (count--) { *((char*)dest + count) = *((char*)src + count); } } return ret; } int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9 }; my_memmove(arr + 2, arr, 16); //my_memmove(arr, arr + 2, 16); return 0; }
my_memcpy(void* dest, const void* src, size_t count) { void* set = dest; assert(dest && src); while (count--) { *(char*)dest = *(char*)src; dest = (char*)dest + 1; src = (char*)src + 1; } return set; } int main() { int arr1[10] = { 1,2,3,4,5,6,7 }; int arr2[20] = { 0 }; my_memcpy(arr2, arr1, 40);//Copying is integer data int i = 0; for (i = 0; i < 20; i++) { printf("%d", arr2[i]); } return 0; }
char* my_strstr(const char*str1, const char* str2) { assert(str1 && str2); char* s1; char* s2; char* cp = str1; if (*str2 == '\0') return str1; while (*cp) { s1 = cp; s2 = str2; //while (*s1!='\0' && *s2 != '\0' && *s1 == *s2) while (*s1 && *s2 && *s1 == *s2) { s1++; s2++; } if (*s2 == '\0') { return cp; } cp++; } //can't find return NULL; } int main() { char arr1[] = "i am good student, hehe student"; char arr2[] = "student"; //Find the first occurrence of arr2 in arr1 char *ret = my_strstr(arr1, arr2); if (ret == NULL) { printf("can't find\n"); } else { printf("%s\n", ret); } return 0; }
#include<string.h> #include<stdio.h> #include<assert.h> my_strcat(char* dest, const char* src) { assert(dest && src); // a b c \0 // d e f \0 //1, find the end of the target string \ 0 //2. Append string until \ 0 //The return type is char *, and strat returns the starting address of the target space char* ret = dest; while (*dest) { dest++; } //Equal to strcpy append while (*dest++ = *src++) { ; } return ret; //The return type is char *, and strat returns the starting address of the target space } int main() { //strcpy string copy \ 0 is a stop flag //stract string connection char arr1[20] = "abc";//Make sure the data can be put in char arr2[20] = { 'd','e','f' };//No \ 0 programs will have problems char arr3[20] = { 'd','e','f' ,'\0' };//Correct writing my_strcat(arr1, arr3); printf("%s\n", arr1); return 0; }
int my_strcmp(const char* s1,const char* s2) { assert(s1 && s2); // a b c d e \0 // a d n \0 //c and n are not equal, compare assic value // a b c \0 // a b c \0 //equal while (*s1 == *s2) { if (*s1 == '\0') { return 0; } s1++; s2++; } return *s1 - *s2;//If the first string is smaller than the second string, a negative number is returned } int main() { char arr1[] = "asihvw"; char arr2[] = "asns"; //String one by one comparison //The return value has three possibilities //If equal \ 0 is found, stop and the result is 0; //The different comparison is the assic code value corresponding to the string int ret = my_strcmp(arr1, arr2); if (ret == 0) { printf("=\n"); } else if (ret < 0) { printf("<\n"); } else { printf(">\n"); } printf("%d\n", ret); return 0; }
char* my_strcpy(char* dest, const char* src) { assert(dest && src); char* ret = dest; while (*dest++ = *src++) { ; } return ret; } int main() { char arr1[] = "xxxxxxxx"; char arr2[] = "abc"; printf("%s\n", my_strcpy(arr1, arr2)); return 0; }
int my_strlen(const char* str) { int count = 0; while (*str !='\0') { count++; str++; } return count; } int main() { char arr1[] = "sfsgssg"; int ret = my_strlen(arr1); printf("%d",ret); return 0; }
5, Custom types: structure, enumeration, union
1. Structure
Declaration of structure
struct tag { member-list; }variable-list;
Self reference of structure
struct Node { int data; struct Node* next; };
Definition and initialization of structure variables
int x, y; struct Point { int x; int y; }p1; //Define the variable p1 while declaring the type struct Point p2; //Define structure variable p2 //Initialization: define variables and assign initial values at the same time. struct Point p3 = { x, y }; struct Stu //Type declaration { char name[15];//name int age; //Age }; struct Stu s = { "zhangsan", 20 };//initialization struct Node { int data; struct Point p; struct Node* next; }n1 = { 10, {4,5}, NULL }; //Structure nesting initialization struct Node n2 = { 20, {5, 6}, NULL };//Structure nesting initial h,
Structure memory alignment
This section is explained in detail in my previous blog. It is suggested that archaeologists are welcome. It is difficult to get started on the following problems without understanding the alignment of structures
❤️ Graphic C language, structure alignment, nanny level teaching, suggestions collection ❤️
Alignment rules for structures
1. The first member of the structure is always placed at the address with the starting position offset of 0
2. The structure from the second member is always placed in an integer multiple of an aligned number
Alignment number = the compiler's default alignment number and the smaller value of the variable's own size
3. The total size of the. Structure is an integer multiple of the maximum alignment number (each member variable has an alignment number).
4. If a structure is nested, the nested structure is aligned to an integer multiple of its maximum alignment number, and the overall size of the structure is an integer multiple of all the maximum alignment numbers (including the alignment number of nested structures).
Why is there memory alignment
1. Platform reason (migration reason): not all hardware platforms can access any data at any address; Some hardware platforms can only get certain types of data at certain addresses, otherwise hardware exceptions will be thrown.
2. Performance reason: data structures (especially stacks) should be aligned on natural boundaries as much as possible. The reason is that in order to access misaligned memory, the processor needs to make two memory accesses; Aligned memory access requires only one access.
int main() { struct S1 { char c1; int i; char c2; }; printf("%d\n", sizeof(struct S1)); return 0; }
c1 is an address with an offset of 0 at the starting position of the structure.
i is the second member. It is always placed in an integer multiple of an alignment number. Alignment number = the smaller value of the compiler's default alignment number and the size of the variable itself. i itself is 4 and Vs is 8 by default. We choose to start from 4 and discard all in the middle.
c2 itself is a byte, which is still 1 compared with Vs8.
According to the third rule, the total size of the structure is an integer multiple of the maximum alignment number (each member variable has an alignment number).
The maximum alignment digit is 4. At this time, our memory is 8, and the total size is 9. Continue to extend to 11, and the total size is 12, which is an integer multiple of 4, in line with the third rule.
int main() { struct S1 { char c1; //Byte size 1 Vs is 8, so it is 1 int i; //Byte size 4 Vs is 8, so it is 4 char c2; //Byte size 1 Vs is 8, so it is 1 }; printf("%d\n", sizeof(struct S1)); return 0; }
c1 is an address with an offset of 0 at the starting position of the structure.
c2 is the second member. It is always placed in an integer multiple of an alignment number. Alignment number = the compiler's default alignment number and the smaller value of the variable's own size. c2 itself is 1 and Vs is 8 by default. We choose to start from 1.
i itself is 4 bytes, which is still 4 compared with Vs8.
According to the third rule, the total size of the structure is an integer multiple of the maximum alignment number (each member variable has an alignment number).
The maximum alignment digit is 4. At this time, our memory is 7 and the total size is 8, which is an integer multiple of 4, in line with the third rule.
int main() { struct S3 { double d; char c; int i; }; printf("%d\n", sizeof(struct S3)); return 0; }
d address offset to 0 at the starting position of the structure.
c is the second member. It is always placed in an integer multiple of an alignment number. Alignment number = the compiler's default alignment number and the smaller value of the variable's own size. c2 itself is 1, Vs is 8 by default. We choose to start from 8.
i itself is 4 bytes, which is still 4 compared with Vs8. But it must start from 12, because the memory is 9 at this time, which should comply with the second rule.
According to the third rule, the total size of the structure is an integer multiple of the maximum alignment number (each member variable has an alignment number).
The maximum alignment digit is 4. At this time, our memory is 15, and the total size is 16, which is an integer multiple of 8, in line with the third rule.
int main() { struct S3 { double d; char c; int i; }; printf("%d\n", sizeof(struct S3)); struct S4 { char c1; // struct S3 s3; double d; }; printf("%d\n", sizeof(struct S4)); return 0; }
c1 is an address with an offset of 0 at the starting position of the structure.
According to the fourth rule, the nested structure is aligned to the integer multiple of its maximum alignment number, and the maximum integer multiple of S3 is 8. Therefore, we must start from 8 and discard it in the middle. The structure S3 itself is 16 and extend backward from 16 to 23
d is 8 bytes, complying with the rule from 24
According to the third rule, the total size of the structure is an integer multiple of the maximum alignment number (each member variable has an alignment number).
The maximum alignment digit is 16. At this time, our memory is 23, and the total size is 24. Continue to extend to 31, and the total size is 32, which is an integer multiple of 16, in line with the third rule.
In a 32-bit system environment, if the compilation option is 4-byte alignment, sizeof(A) and sizeof(B) are ()
struct A { int a; short b; int c; char d; }; struct B { int a; short b; char c; int d; };
Both structures are aligned with int. In structure a, a aligns a 4 byte alone, and b+c exceeds 4 bytes, so B aligns a 4 byte alone, c aligns a 4 byte alone, and the remaining d aligns a 4 byte alone, a total of 16 bytes. In structure B, a aligns a four byte alone, and b+c+d exceeds four bytes, so B and c align a four byte together, and d aligns a four byte alone, a total of 12 bytes
The result of the following code is: ()
#pragma pack(4) / * compilation option, indicating 4-byte alignment platform: VS2013. Language: C language*/ int main(int argc, char* argv[]) { struct tagTest1 { short a; char d; long b; long c; }; struct tagTest2 { long b; short c; char d; long a; }; struct tagTest3 { short c; long b; char d; long a; }; struct tagTest1 stT1; struct tagTest2 stT2; struct tagTest3 stT3; printf("%d %d %d", sizeof(stT1), sizeof(stT2), sizeof(stT3)); return 0; } #pragma pack()
The three structures are aligned with the longest 4-byte long. The first a+d+b only exceeds 4 bytes, so a and d align a 4 byte together, and the remaining two occupy it alone, a total of 12 bytes. Similarly, the second c and d align a four byte, also 12 bytes. In the third, because c+b and d+a are more than 4 bytes, they are aligned with a 4 byte, a total of 16 bytes.
In VS2013, the space occupied by this structure is () bytes
typedef struct{ int a; char b; short c; short d; }AA_t;
16. Refer to the above calculation method
Bit segment
The declaration and structure of bit segments are similar, with two differences:
1. The member of the bit field must be int, unsigned int or signed int.
2. There is a colon and a number after the member name of the bit field.
struct A { int _a:2; int _b:5; int _c:10; int _d:30; };
Memory allocation for bit segments
1. The member of the bit segment can be int unsigned int signed int or char (belonging to the shaping family)
2. The space of bit segment is opened up in the way of 4 bytes (int) or 1 byte (char) as required.
3. Bit segments involve many uncertain factors. Bit segments are not cross platform. Pay attention to portable programs and avoid using bit segments.
struct S { char a : 3; char b : 4; char c : 5; char d : 4; }; int main() { struct S s = { 0 }; s.a = 10; s.b = 12; s.c = 3; s.d = 4; return 0; }
Cross platform problem of bit segment
1. It is uncertain whether the int bit field is regarded as a signed number or an unsigned number.
2. The number of the largest bits in the bit segment cannot be determined. (16 bit machines have a maximum of 16 and 32-bit machines have a maximum of 32, which is written as 27. Problems will occur on 16 bit machines.
3. Whether the members in the bit segment are allocated from left to right or from right to left in memory has not been defined.
4. When a structure contains two bit segments, and the member of the second bit segment is too large to accommodate the remaining bits of the first bit segment, it is uncertain whether to discard the remaining bits or use them.
Compared with the structure, bit segment can achieve the same effect, but it can save space, but there are cross platform problems.
2. Enumeration
Definition of enumeration type
enum Day//week { Mon, Tues, Wed, Thur, Fri, Sat, Sun };
Advantages of enumeration
1. Increase the readability and maintainability of the code
2. Compared with #define defined identifiers, enumeration has type checking, which is more rigorous.
3. Prevent naming pollution (packaging)
4. Convenient for debugging
5. Easy to use, multiple constants can be defined at a time
3. Consortium
definition
//Declaration of union type union Un { char c; int i; }; //Definition of joint variables union Un un; //Calculate the size of multiple variables printf("%d\n", sizeof(un));
Characteristics of joint
The members of the union share the same memory space. The size of such a union variable is at least the size of the largest member (because the union must be able to save the largest member at least).
Calculation of joint size
The size of the union is at least the size of the maximum member. When the maximum member size is not an integer multiple of the maximum alignment number, it should be aligned to an integer multiple of the maximum alignment number.
union Un1 { char c[5]; int i; }; union Un2 { short c[7]; int i; }; //What is the output below? int main() { printf("%d\n", sizeof(union Un1)); printf("%d\n", sizeof(union Un2)); return 0; }
There are the following macro definitions and structure definitions
#define MAX_SIZE A+B struct _Record_Struct { unsigned char Env_Alarm_ID : 4; unsigned char Para1 : 2; unsigned char state; unsigned char avail : 1; }*Env_Alarm_Record; struct _Record_Struct *pointer = (struct _Record_Struct*)malloc (sizeof(struct _Record_Struct) * MAX_SIZE);
Note: the structure is aligned to the longest char. The first two bit segment elements have a total of 4 + 2 bits, less than 8 bits, accounting for 1 byte in total, and the last single byte has a total of 3 bytes. In addition, #define performs search and replacement. The sentence sizeof(struct _Record_Struct) * MAX_SIZE is actually 3 * 2 + 3, and the result is 9
The result of the following code is ()
int main() { unsigned char puc[4]; struct tagPIM { unsigned char ucPim1; unsigned char ucData0 : 1; unsigned char ucData1 : 2; unsigned char ucData2 : 3; }*pstPimData; pstPimData = (struct tagPIM*)puc; memset(puc,0,4); pstPimData->ucPim1 = 2; pstPimData->ucData0 = 3; pstPimData->ucData1 = 4; pstPimData->ucData2 = 5; printf("%02x %02x %02x %02x\n",puc[0], puc[1], puc[2], puc[3]); return 0; }
A.02 03 04 05
B.02 29 00 00
C.02 25 00 00
D.02 29 04 00
puc is a char array. It jumps one byte at a time. The structure is not. Only the first element enjoys one byte separately, and the other three elements share one byte together. Therefore, after puc is filled by the structure, only two bytes will be written. The last two bytes must be 0. AD is excluded. Then the first byte is 2, which is 2. The second byte is more troublesome First, ucData0 gives 3, which is actually out of bounds. The number of 1 bit can only be 0 or 1, so only 1 after 11 is truncated. Similarly, ucData1 gives 4 out of bounds, 00 after 100 is truncated, and only 101 of 5 is normal. The filling sequence is similar to the low address of the small end, so the order is 00 101 00 1. That is, 0010 1001, 0x29, so B is selected.
The result of the following code is: ()
#include <stdio.h> union Un { short s[7]; int n; }; int main() { printf("%d\n", sizeof(union Un)); return 0; }
The structure is aligned to int. the seven short are 14 bytes in total and 16 bytes after alignment. n is a separate 4 bytes. Because it is a union, n and s share the space and only take the longest element, so it occupies 16 bytes.
Under X86, there are the following procedures
#include<stdio.h> int main() { union { short k; char i[2]; }*s, a; s = &a; s->i[0] = 0x39; s->i[1] = 0x38; printf("%x\n",a.k); return 0; }
The union has only 2 bytes, and the hexadecimal of 2 bytes has only 4 bits, so the answer CD is excluded. The bit order is similar to the small end. The low address is in the low position, so 39 is the low address, in the low position, and 38 is in the high position, so it is 3839,
The result of the following code is: ()
enum ENUM_A { X1, Y1, Z1 = 255, A1, B1, }; enum ENUM_A enumA = Y1; enum ENUM_A enumB = B1; printf("%d %d\n", enumA, enumB);
Enumeration starts from 0 by default, so X1 is 0, so Y1 is 1. After a number is given, it will be pushed back according to the number. Then Z1 is 255, A1 is 256, so B1 is 257,
6, Dynamic memory management
This section is also explained in detail in my previous blog. Welcome to archaeology
Playing with dynamic memory management of C language
1. Why is there dynamic memory allocation
The size of the space is fixed.
When declaring an array, you must specify the length of the array, and the memory it needs will be allocated at compile time.
2. Introduction to dynamic memory functions
C language provides a function of dynamic memory development
void* malloc (size_t size)
If the development is successful, a pointer to the developed space is returned.
If the development fails, a NULL pointer is 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 open space, which is determined by the user when using it.
If the parameter size is 0, malloc's behavior is standard and undefined, depending on the compiler.
C language provides another function free, which is specially used for dynamic memory release and recovery
void free (void* ptr);
If the space pointed to by the parameter ptr is not dynamically opened up, the behavior of the free function is undefined.
If the parameter ptr is a NULL pointer, the function does nothing.
C language also provides a function called calloc, which is also used for dynamic memory allocation. The prototype is as follows
void* calloc (size_t num, size_t size);
The function is to open up a space for num size elements, and initialize each byte of the space to 0.
The only difference between calloc and malloc is that calloc initializes each byte of the requested space to all zeros before returning the address.
The emergence of realloc function makes dynamic memory management more flexible. Sometimes we find that the space applied for in the past is too small, and sometimes we think that the space applied for is too large. That's for the sake of reasonable memory.
void* realloc (void* ptr, size_t size);
ptr is the memory address to be adjusted
New size after resizing
The return value is the adjusted memory starting position.
This function adjusts the size of the original memory space,
It also moves the data in the original memory to a new space.
The wrong statement about dynamic memory function is: ()
A. The malloc function requests a contiguous space from memory and returns the starting address
B.malloc failed to apply for space and returned NULL pointer
C.malloc can request 0 bytes of space from memory
D. The memory space requested by malloc will not be released nor will it affect the program
Memory fragmentation will occur if it is not released. Small programs may not pay attention to it, but it has a profound impact on medium and large programs. So choose D. AB is the basic function of the function. The C option is special. malloc(0) is allowed and a pointer will be returned. However, there is no space, so it cannot be used.
Which area of memory is dynamically requested? ( )
A. Stack area
B. Heap area
C. Static zone
D. Text constant area
State memory allocation is allocated on the heap
Which of the following is not a dynamic memory error ()
A. The free parameter is NULL
B. free release of non dynamic memory
C. Multiple releases of dynamic memory
D. Out of bounds access to dynamic memory
Option A is right. The free function passes A NULL pointer and nothing happens
B. C and D are all wrong
The wrong statement about dynamic memory correlation function is: ()
A.malloc function and calloc function have similar functions. They both apply for a continuous space.
B. The space requested by malloc function is not initialized, and the space requested by calloc function will be initialized to 0
C.realloc function can adjust the size of dynamically applied memory, which can be large or small
D. The free function cannot release realloc adjusted space
Realloc releases the old space allocation and returns the new space during the operation, so the returned new space also needs to be released, so select D. AB is the difference between malloc and calloc. C is the basic function of realloc.
7, C language file operation
A blog I wrote before has a very detailed explanation of this chapter. Nanny level teaching. It is recommended that readers read and learn this article and then do the following exercises to get twice the result with half the effort!!!
What is the method for C language to open a file in binary mode? ( )
A.FILE *f = fwrite( "test.bin", "b" );
B.FILE *f = fopenb( "test.bin", "w" );
C.FILE *f = fopen( "test.bin", "wb" );
D.FILE *f = fwriteb( "test.bin" );
First, to open the file, drag AD directly. Since there is no "fopenb" function, select C directly. b in binary description should be placed after permission, that is, "wb" is legal.
The incorrect statement about fopen function is: ()
A.fopen opens the file by "r". If the file does not exist, opening the file fails
B.fopen opens the file by "w". If the file does not exist, the file is created and opened successfully
C. The return value of fopen function needs no judgment
D.fopen open files need fclose to close
The return value of fopen in the C option can check whether the file is opened successfully, especially when the opening method is "r". ABD is the basic concept and principle of file operation.
The following statements about file names and paths are wrong: ()
A. There are some forbidden characters in the file name
B. The file name must contain a suffix
C. The suffix of a file determines the default opening method of a file
D. File path refers to the collection of symbol names in the path from the drive letter to the file
In option B, the file name may not contain a suffix. A, the file cannot contain these characters: \ /: *? "< > |, C describes the function of suffix, and D is the basic concept of path. Therefore, B is selected.
The incorrect statement about file read-write function in C language is: ()
A.fgetc is a character input function for all input streams
B.getchar is also a character input function for all streams
C.fputs is a text line output function for all output streams
D.fread is a binary input function for file input streams
In the B option, getchar only targets stdin, the standard input stream. Even if stdin is redirected, getchar only targets stdin. The input and output functions of f series act on all streams, so AC is no problem, and the expression of D is no problem. What fread does is binary.
What is the function of the following program? ( )
int main() { long num=0; FILE *fp = NULL; if((fp=fopen("fname.dat","r"))==NULL) { printf("Can't open the file! "); exit(0): } while(fgetc(fp) != EOF) { num++; } printf("num=%d\n",num); fclose(fp); return 0; }
The program only opens a file in read-only mode. fgetc is used in this paper, and there is no statistics related to '\ n' and '\ n', which counts the number of characters in the file
The following statement is incorrect: ()
A.scanf and printf are formatted input and output statements for standard input and output streams
B.fscanf and fprintf are formatted input and output statements for all input and output streams
C.sscanf reads formatted data from a string
D.sprintf writes formatted data to the output stream
In the D option, sprintf writes the formatted data to the string, independent of the output stream. The other three sentences accurately describe the function.