C++ New Classic | C Language

Table of contents

1. Detecting and filling gaps in basics

1.float precision problem

2.Character data

3. Variable initial value problem

4. Assignment & initialization

5.Header file <> VS " "

6. Logical operations

7.Array

7.1 Initialization of two-dimensional array

7.2 Character array

8. String processing functions

8.1 cracked

8.2 strcpy

8.3 strcmp

8.4 stlen

9. Function

9.1 Katasan

9.2 Global variables

9.3 Variable storage method

(1) Storage space

(2) What data is stored in the dynamic storage area?

(3) What data is stored in the static storage area?

9.4 Usage of static keyword

10. Compilation preprocessing

10.1 Compilation

10.2 Preprocessing

10.3 Macros VS Functions

11. Structure & Union

11.1 Structure

11.2 Community

12. Bit operations

12.1 Applications of bit operations

13.Documents

13.1 File classification

13.2 Several characteristics of text files

13.3 Disadvantages of text files

13.4 fopen function

13.4 fputc & fgetc functions

13.5 feof function

13.6 \r\n

2. Debugging skills

 1. Memory view


1. Detecting and filling gaps in basics

1.float precision problem

         When assigning a decimal value to a real variable, the computer will convert the decimal number into a binary number and save it. When the program execution flow stops at the breakpoint and the variable value is viewed with the mouse, the computer actually saves it. The binary number is then converted into a decimal number and displayed. In this step - "Decimal → Binary, Binary → Decimal", there are some division operations. These division operations will cause the conversion from binary back to decimal number due to the reason that they cannot be divided. Loss of precision.

2.Character data

        Putting a character constant into a character variable does not actually put the character itself into the memory to which the character variable belongs, but stores the ASCII code (a number) corresponding to the character into the memory.

        What is ASCII code? In layman's terms, it is an integer (number) ranging from 0 to 127. For example, the number corresponding to the character a is 97, and the number corresponding to the character b is 98.

        Since character data is stored in ASCII code in memory, it means that the storage form of character data is similar to that of integers. Therefore, in C language, character data and integer data can be used interchangeably. A character data can be output in character form or integer form. When output in character form, the computer will first The ASCII code is converted into corresponding characters and then output.

        The character 'a' occupies 1 byte in memory, while "a" occupies 2 bytes in memory. The last character of "a" is '\0', which is an escape character. That is to say, "a" is actually composed of two characters, but if '\0' appears in printf for output, it will not It will not be output, but will be used as a string end marker to mark the end of the string content.

        When writing a string constant, do not add '\0' manually. This is superfluous. '\0' is added by the system.

3. Variable initial value problem

        In C language, when defining a variable, the value stored in the variable that is not assigned an initial value is uncertain. Therefore, the variable that is not assigned an initial value should not be used to participate in operations.

        Compared to C#, the rules are different. In C#, the default value of a variable is determined by its type. For an integer variable (such as int), if you just declare it without assigning a value to it, its default value will be automatically set to 0.

4. Assignment & initialization

       The following line of code is not an assignment statement. It is more appropriately called a definition-time initialization (initial value is given when defining) statement, because there is a type identifier char at the beginning of this line of code (an assignment statement cannot start with a type name as the statement) ):

int a = 10;

5.Header file <> VS " "

        When a header file enclosed in angle brackets <> is #included, it means that Visual Studio is asked to search for the .h file in the system directory. Therefore, some standard header files provided by the system, such as stdio.h, stdlib.h, etc., are included when #included. It should be enclosed in angle brackets <>.

        When a header file enclosed in double quotes " " is #included, Visual Studio will first search in the directory where the current source code file is located. If it cannot be found, it will search in the system directory. Therefore, developers usually write it themselves Some header files are often included in double quotes "" when included by #include.

6. Logical operations

        Many logical expressions only need to calculate part of the content to obtain the value of the entire logical expression. This evaluation characteristic of logical expressions is also called the "short-circuit evaluation" characteristic of logical expressions (as long as the final result It can be determined whether it is true or false, and the evaluation process is terminated).

7.Array

7.1 Initialization of two-dimensional array

        The general format for defining a two-dimensional array in C language: type description array name [constant expression] [constant expression], eg:

int a[3][4];  //不能把两个中括号写成一个,a[3,4]是错误的写法

Declaration and initialization of two-dimensional arrays in C#:
int[,] array = new int[3, 4] {     {1, 2, 3, 4},     {5, 6, 7, 8},     {9,10,11 ,12} };



7.2 Character array

        The character array can store not only characters but also strings. As long as you initialize the character array with a string (recommended), the system will automatically add a '\0' at the end of the string.

char str[6] = "Hello"

        So if you want to use the method of assigning a value to each element in the character array separately (but this way of writing is very rare, and it is not recommended to assign a value to each element separately) to initialize the character array, it is recommended to keep it consistent with the string, that is, artificially Add a '\0'. This is mainly done to determine the actual length of the string (because the actual length of the string is determined by finding the '\0' at the end).

8. String processing functions

8.1 cracked

        strcat(Character array 1,Character array 2);

        Concatenate the strings in the two character arrays, connect the contents of character array 2 to the end of character array 1, and store the result in character array 1.

  • Character array 1 must be large enough to accommodate the new string after concatenation.
  • Before concatenation, there is a \'0' after the two strings. During concatenation, delete the \'0' at the end of string 1 and start concatenating the contents of string 2. After concatenation, only a '\' will be left at the end of the new string. 0'.
  • The content of str2 does not change after the connection. In other words, strcat has no effect on str2.

8.2 strcpy

        strcpy(Character array 1, String 2);

        Copy string 2 into character array 1. The contents of character array 1 will be overwritten.

  • Character array 1 must be large enough to accommodate the copied string. That is to say, the capacity of character array 1 cannot be less than the length of string 2 (don’t forget that there is a '\0' at the end of string 2 as well. a location).
  • Character array 1 must be an array name, while string 2 can be an array name or a string constant.
  • When copying, the '\0' at the end of the string is also copied to the character array.
  • You cannot use an assignment statement to directly assign a string constant or character array name to a character array (character array name). You must use the strcpy function. The assignment statement can only assign a character to a character variable or array element.
  • The content of str2 will not change after copying. Although there are two \'0's in str1, when the string content is output, it will only be output before the first '\0'.

8.3 strcmp

        strcmp(String1,String2);

        Compare the contents of string 1 and string 2. This is also a commonly used function:

  • If string1=string2, the function returns 0.
  • If string1>string2, the function returns a positive integer.
  • If string1<string2, the function returns a negative integer.

        Comparison rules: Compare two strings character by character from left to right (compare according to ASCII code value) until different characters appear or '\0' is encountered. If all characters are the same, they are considered equal. If they are not If the characters are the same, the comparison result of the first different character shall prevail.

        Generally speaking, strcmp is often used to compare whether two strings are equal, but it is less used to compare sizes, because comparing sizes is generally not meaningful.

8.4 stlen

        strlen(char array);

        Get the string length. The result value of this function is the actual length of the string, but does not include the string end mark '\0'.

9. Function

        The system will allocate some memory for function calls to save some information (local variables, function parameters, function call relationships, etc.)

9.1 Katasan

(1) When a function is called, memory will be allocated for the formal parameters of the function. After the function call is completed, the memory of the formal parameters will be released, so the formal parameters can only be used inside the function.

(2) The size of the formal parameter group does not need to be specified. Even if it is specified, it may not be consistent with the size of the actual parameter group, because the C compiler does not check the size of the formal parameter group and only passes the first address of the actual parameter group to the formal parameter group. You can even define the formal parameter group size to be larger than the actual parameter group size, but do not reference the part of the memory that exceeds the actual parameter group size, otherwise the program will crash immediately or irregularly.

(3) Multidimensional array names can be used as formal parameters and actual parameters. When defining a formal parameter group, you can specify the size of each dimension, or you can omit the size of the first dimension, but you cannot omit the size of the second dimension. Please remember one thing: the actual parameters are as many rows and columns as possible, and the formal parameters should be the same as the actual parameters (also these rows and columns). In this way, the subscripted formal parameters that can be referenced by the actual parameters can also be referenced, which will ensure that the code written is not An error occurred.

(4) Formal parameters are local variables.

9.2 Global variables

        From the perspective of the scope of variables, they can be divided into local variables and global variables.

(1) Advantages and disadvantages of global variables:

*advantage:

        Added channels for data connection between functions. If the value of a global variable is changed in a function, it can affect other functions that use the global variable. This is equivalent to having a direct channel for transferring data between functions, without the need to pass actual parameters or formal parameters. Passed the data. Because functions in C language can only return one value (cannot return multiple values ​​at once), if you use global variables, it is equivalent to being able to return multiple values ​​​​from the function.

*shortcoming:

  • Only use global variables when necessary (use with caution), because global variables occupy memory throughout the execution of the program, unlike local variables within a function. When the function completes, the memory occupied by these local variables will Released (recycled) by the system.
  • Reduced function versatility, because the function execution may depend on these global variables. If the function is migrated to another source program file, the global variables related to the function also need to consider migration issues, and if the target source is migrated to There are also global variables with the same name in the program file, which is more troublesome.
  • There are global variables everywhere, which reduces the clarity and readability of the program. It is difficult for people who read the program to clearly judge the value of each global variable at each moment (because many functions can change the value of the global variable).

(2) If a function wants to reference a global variable defined after it, you can use the keyword extern to make an "external variable description", indicating that the variable is defined outside the function, so that it can be used within the function, otherwise the compilation will fail. An error will occur, but one thing to note is that global variables can be given initial values ​​when they are defined, but when external variables are declared, initial values ​​cannot be given to variables.

int main()
{
    extern int value;
    std::cout << "value:" << value << std::endl;
}

int value = 20;

(3) In the same source file, if the global variable and the local variable have the same name, the global variable has no effect within the scope of the local variable. If a value is assigned to the local variable, it will of course not affect the global variable. value.

(4) If the global variables defined in one source program file want to be used in other source program files of the project, you only need to use the extern keyword introduced above to make external variable descriptions in other source program files. This global variable is used in other source program files.

        Generally speaking, the scope of a global variable is from the point where it is defined to the end of the entire source program file. However, by using extern, its scope is expanded to other source program files with extern specifications. If there are more source program files to reference this global variable, extern should be used at the beginning of these source program files to indicate that this global variable is an external global variable.

        If you hope that some global variables can only be used in the source program file and do not want to be referenced across files by other source program files, it is also very simple. When defining this global variable, add the static keyword at the front.

9.3 Variable storage method

        If divided from the perspective of the time the variable exists (lifetime), variables can be divided into "static storage variables" and "dynamic storage variables", which leads to "static storage methods" and "dynamic storage methods".

  • Static storage method: a method of allocating fixed storage space during program running.
  • Dynamic storage method: A method of dynamically allocating storage space as needed during program running.

(1) Storage space

        The storage space is divided into three main parts: program code area, static storage area and dynamic storage area. The data required for program execution is placed in the static storage area and dynamic storage area, and the storage area is understood as memory.

(2) What data is stored in the dynamic storage area?

  • Function parameters, as mentioned earlier, function parameters are regarded as local variables.
  • Local variables, such as some variables defined within a function.
  • When the function is called, some data and return address of the calling site are included.

        Generally speaking, this data is allocated storage space at the beginning of the function call, and the space is released (also called recycling) after the function call is completed. This allocation and release is considered dynamic. If the same function is called twice, the storage space address of the local variable assigned to this function may be different.

(3) What data is stored in the static storage area?

        Global variables (including global static variables, defined outside the function) are placed in static storage areas. Storage areas are allocated to global variables when the program starts executing, and these storage areas are released after the program execution is completed. They occupy fixed storage locations during program execution rather than dynamically allocated and released.

        Sometimes it is hoped that the value of a local variable in a function will not disappear (not be automatically released by the system) but retain the original value after the function is called. That is to say, the storage unit it occupies will not be released. The next time the function is called, the variable will be saved. The value is the value at the end of the last function call. This can be done by specifying the local variable as a " local static variable " and using the static keyword to explain it. Local static variables:

  •  The storage unit is allocated in the static storage area and will not be released during the entire running of the program. ·
  • Local static variables are assigned an initial value at compile time. The initial value is only assigned once. It already has an initial value when the program is running. It will not reassign the initial value every time the function is called in the future, but only retains the end of the last function call. The value at the time, while the definition and assignment of ordinary variables are only performed when the function is called.
  • If you do not assign an initial value when defining a local static variable, it will automatically be assigned an initial value of 0 during compilation. However, if a regular variable is not assigned an initial value, it will have an uncertain value.
  • Although local static variables still exist after the function call ends, they cannot be referenced in other functions.
  • Local static variables occupy memory for a long time, reducing the readability of the program (when the function is called multiple times, it is often unclear what the current value of the static variable is).

        So we come to a conclusion: Don't use local static variables too much unless necessary.

9.4 Usage of static keyword

(1) When defining a local variable inside a function, if the static keyword is used in front, the variable will be saved in the static storage area and initialized during compilation. If no initial value is given, its value will be initialized to 0. , and the next time the function is called the variable retains the value it had when the function was last left.

(2) If the static keyword is used before defining a global variable, the global variable can only be used in this file and cannot be referenced (used) in other files.

(3) Add static before the function definition, then the function can only be called in the original source program file and cannot be called in other source program files.

10. Compilation preprocessing

        A project consists of one or more source program files, which can be compiled and linked (Visual Studio is responsible for doing this) and finally generate an executable file.

10.1 Compilation

        Compilation is performed in units of source program files (.cpp files). Each source program file will be compiled into a target file (the target file extension may be .o or .obj, etc., which is different from the operation (depending on the system type), if there are multiple source program files, multiple object files will be compiled and then linked, and finally an executable file will be generated.

        Generally speaking, the compilation phase will do the following things:

  • preprocessing.
  • Compile. Including lexical analysis, syntax analysis, target code generation, optimization, etc.
  • compilation. Generates .o (.obj) object files.

10.2 Preprocessing

        C language generally provides three preprocessing functions: macro definition, file inclusion, and conditional compilation. These three preprocessing functions are also implemented by writing codes in the source program files, but these codes are special and all start with "#".

        The macro definition is not actually a C language statement (although it is sometimes called a statement). There is no need to add a semicolon at the end of the line. If a semicolon is added, the semicolon will be replaced.

10.3 Macros VS Functions

  • If the number of macros used increases, the source program code will increase, but function calls will not increase the source program code.
  • Macro expansion only takes up compilation time and does not take up running time, while function calls take up running time (allocating memory, passing parameters, executing function bodies, return values, etc.)

11. Structure & Union

11.1 Structure

        In C language, the "struct" keyword must be included when declaring a structure variable (unless a new type is created with typedef), but it is not necessary in C++.

struct Person {
    char name[50];
    int age;
};

struct Person person;
strcpy(person.name, "Alice");
person.age = 20;

11.2 Community

        The memory size occupied by the structure is the sum of the memory size occupied by each member, and each member occupies a different section of memory. Because the members of a union occupy the same memory, the memory size occupied is equal to the memory size occupied by the member occupying the largest memory, rather than the sum of the memory sizes occupied by each member.

        The addresses of union variables and the addresses of its members are the same. The union variable name also represents the first address of the union variable, which is similar to the argument that the array name represents the first address of the array.

        A union variable cannot initialize all members when it is defined, but it is allowed to initialize the first member when it is defined.

12. Bit operations

        1 byte is composed of 8 binary bits. The leftmost bit is called the highest bit, and the rightmost bit is called the lowest bit. The value of each binary bit is 0 or 1 (binary numbers have only two digits 0 and 1. It cannot be any other number).

        The range of numbers that can be represented by 1 byte. If expressed in binary numbers, the maximum binary number that can be represented is 11111111 (decimal number 255), and the minimum binary number is 00000000 (which is 0). 1 byte can represent 8 binary bits, what about 4 bytes? Obviously, it can represent 32 binary bits. The left side of the equal sign is a binary number (32 binary digits), and the right side of the equal sign is a decimal number:

11111111,11111111,11111111,11111111=4294967295

        Therefore, the decimal number 4294967295 is the largest number that the unsignedint type can represent.

12.1 Applications of bit operations

        If some binary bits of a number want to be flipped (from 0 to 1, from 1 to 0), then this bit can be XORed with 1. If some binary bits want to remain unchanged, then this bit can Do XOR operation with 0.

        The left shift operator "<<" shifts the binary digits of a number to the left by a number of bits, and adds 0 on the right. Each left shift of one bit is equivalent to multiplying the original number by 2.

        The right shift operator ">>" shifts the binary digits of a number to the right by a certain number of bits. The bits beyond the lowest bit are discarded, and the high bits on the left are filled with 0. Each right shift by one bit is equivalent to dividing by 2.

13.Documents

13.1 File classification

        According to the data organization form, files are divided into two types: text files (ASCII files) and binary files.

  • Text file: Also known as ASCII file, each byte in the file stores an ASCII code, representing a character. This kind of file can directly understand the content after opening it.
  • Binary file: Output the data in the memory to the disk and store it as it is stored in the memory. There are usually a lot of invisible characters in this kind of file, and what you see when you open it may be a bunch of garbled characters.

13.2 Several characteristics of text files

  • In a text file, each byte stores an ASCII code, representing a character.
  • The content in the text file can be read by humans.
  • An integer 10000 is saved in text file format. By observing Figure 12.5, it occupies 5 bytes.

13.3 Disadvantages of text files

  • As we all know, 10000 is an integer. In the computer, it is enough to save this number with short int. Short int only occupies 2 bytes, but saving it in a text file requires 5 bytes, so this way of saving takes up a lot of storage. The space is relatively large.
  • When you double-click a text file, or when you open a text file with a binary editor, the system displays the text content that humans can read. (As mentioned earlier, text files or binary files are for humans, but for computers, it does not distinguish what type of file it is, and all binary data is saved) Therefore, when opening a file in text form, the system will One job is to convert binary data into ASCII code data that humans can understand.

13.4 fopen function

        The file must be opened before reading or writing, and must be closed after reading or writing is completed, otherwise it will cause resource leakage or read and write failures. To open a file, call the fopen function.

   FILE* fp = fopen("", "r");

        FILE structure: Every time you use the fopen function to open a file, the system will open up a piece of memory. The size of this memory is sizeof (FILE). This memory is used to store information related to the file, such as file name, file usage method, Current file location, etc. By calling the fopen function, you can tell the system three pieces of information: (1) The name of the file that needs to be opened. (2) How the file is used, such as reading or writing. (3) Let which pointer variable point to the opened file.

        Each open file has a current position pointer, which is actually a char* character pointer stored in the FILE structure (different versions of compilers may have different details, but the principle is the same). The purpose of this position pointer is to represent the current position in the file from which to start reading/writing data. For reading, every time 1 byte of data is read, the position pointer will automatically move back 1 byte to point to the next byte. , in this way, the next time you read it, you will naturally start from the next byte.

13.4 fputc & fgetc functions

        The fputc function is used to write a character to a disk file. The fgetc function is used to read a character from the specified file. If these two functions fail to execute or the entire file is read to the end, EOF is returned.

        EOF is the abbreviation of EndOfFile (end of file). It is a macro definition provided by the system and represents -1. EOF (-1) can be used to determine whether the read content reaches the end of the file. But once there is a character with a value of -1 in the file (the hexadecimal value of this character is FF, and it is -1 when read with fgetc), then use the EOF judgment method to judge whether the end of the file has been read. , an error will occur, so you need to change the writing method and introduce the feof function.

13.5 feof function

        Used to determine whether the file ends (whether the current position pointer of the file points to the end of the file). If the file ends, it returns 1; if the file does not end, it returns 0.

while(!feof(fp))
{
    //...
}

        No matter what file usage method is used to open the file when using the fopen function (for example, it doesn't matter whether you use r or rb), the feof function can correctly determine whether the file ends.

13.6 \r\n

        In the Windows environment, there are two binary numbers at the end of each text line - "0D 0A". By querying the complete ASCII code table, it is not difficult to find that 0D represents the carriage return character and 0A represents the line feed character. That is: each line of a text file usually ends with \r\n. However, when using fgets() to read a file, it will only treat \n as a line terminator, and that will also be stored in the buffer.

        On the Windows platform, if the file is opened for reading, the characters read without the "b" mark may be missing, such as '\r'. If the file is opened for writing, some extra characters may be written to the file without the "b" flag (originally only wanting to write '\n', but actually writing '\r' and '\n '). Therefore, if you want to write the content you see into the file intact, please add the "b" mark to the file usage parameter of the fopen function to assist; if you want to read the content in the file intact, Please add the "b" tag to the file usage parameter of the fopen function to assist.

2. Debugging skills

 1. Memory view

        During breakpoint debugging, select the "Debug" → "Window" → "Memory" → "Memory 1" command to open the "Memory" viewing window. You only need to enter the memory address in it to see the memory address corresponding to the address. Contents in memory.

        Double-click the aaa variable name, hold down the left mouse button and drag it to the edit box on the right side of "Address" in the upper left corner. At this time, the contents of the memory address represented by the variable aaa will be displayed in the "Memory" viewing window.

         In the "Memory" viewing window, the "Address" section in the upper left corner displays 0x0039FA8C, which is the memory address represented by the array aaa. Looking down, it is divided into three parts:

  • The memory address displayed on the left part is the address of aaa and the immediately adjacent memory address;
  • The middle part shows the hexadecimal digital content saved in the memory address (the data saved in the memory are all binary data, but for the convenience of observation, Visual Studio displays these binary data in hexadecimal form, four-digit binary The number is displayed as a hexadecimal digit);
  • The right part shows some displayable characters represented by hexadecimal numbers in the memory. You can find the words "123456789a". By comparing character by character, you can see that the escape character '\0' is in the memory. The hexadecimal number displayed is 00. For other characters, the hexadecimal number displayed in the memory for the 'a' character is 61. The hexadecimal number 61 corresponds to the decimal number 97, and the decimal number 97 is exactly the character. The ASCII code of 'a', so when a character is stored in memory, what is stored is actually the ASCII code of the character.

Guess you like

Origin blog.csdn.net/weixin_39766005/article/details/132541107