Reread classics: "C and Pointers" the first chapter of the study notes to the Nineth Chapter
"C and Pointers", "c expert programming", "C Traps and defects" and called C language three classics, the author swallowed read these three classics many years ago, and then put the three books on the shelf. To this day, most of the content has been forgotten, some time ago accidentally turned out, reread these classics, by the way take notes, record their essence.
C and Pointers help programmers incorporate the power of pointers into their own programs by exploring the basics of pointers and advanced features.
The 1th chapter is quick to get started
This chapter is about the basic knowledge of C language, which aims to make readers have a general understanding of C language.
This chapter gives the reader some advice, including:
- When you use/* and/* to make block comments, you need to be aware of whether the block contains a/such end symbol, as well as a block comment method, that is, using the #ifdef precompiled command
- Note the difference between = and = =, & and && when programming, do not miss or write more
- When calling the scanf function, the passed argument is a pointer type, do not forget to write &
- Use # include directives to avoid duplicate declarations while reducing the amount of code
- The return value of the GetChar () function is an integer rather than a character type ("C Traps and defects" also emphasizes this issue)
Chapter 2nd Basic Concepts
The second chapter still speaks the basic knowledge of C language, the main points of knowledge include:
1, the program's compilation link environment and the operating environment can be different;
Compile and link the program, compiling the source file into the target file, including the replacement of the preprocessor such as define and include; the link is to generate the executable file for the target file and the required library file;
2. Identifiers
- For the length of an identifier, the ANSI standard specifies that the length of the external identifier can be distinguished by at least the first 6 characters and is not case sensitive, and that the internal identifier length can be distinguished by at least the first 31 characters. In order to ensure the portability of code, it is best to strictly abide by this standard. ("C Traps and defects" also highlighted this issue)
- Of course, the identifier of the program ape definition cannot conflict with the C language reserved keyword.
3. Character escapes
C defines some letters preceded by "\" to denote common ASCII characters that cannot be displayed, such as \0,\t,\n, etc., which are called escape characters, because the subsequent character is not its original ASCII character meaning.
There are two ways to express the C language, one is "\" in front of the character, and the other is a three-letter word. Most programs apes only understand the first and are not familiar with the second type.
A three-letter word is a sequence of several characters that together represent another character, such as
| three letter Words |
meaning |
| ?? ( |
[ |
| ?? < |
{ |
| ?? = |
# |
| ??) |
] |
| ?? > |
} |
| ?? / |
\ |
| ??! |
|
| ??’ |
^ |
| ?? - |
~ |
"\" Escape
Partial escape character Definition:
| Escape Character |
meaning |
| \a |
Warning characters that may ring or produce some other visible characters |
| \b |
Backspace |
| \f |
Paper Feed |
| \ n |
Line break |
| \ r |
Enter |
| \ t |
Horizontal tab |
| \v |
Vertical tab |
| \ddd |
Represents 1-3 octal digits, with the given octal number escaped to the corresponding ASCII character |
| \xddd |
Represents 1-3 hexadecimal digits, the given hexadecimal number is escaped to the corresponding ASCII character, and the value may be out of range |
Note:
1,\v Vertical tabulation and \f page breaks have no effect on the screen, but affect the printer's response actions.
2,\n actually should call carriage return to change line. Line break is just a line, do not change the horizontal axis of the cursor, enter just back to the beginning, do not change the vertical axis of the cursor.
3,\t cursor moves forward four or eight cells.
4,\b is the backspace key that moves the cursor forward without deleting the character, but the character may be overwritten by subsequent characters.
5, these are all from the telex typewriter.
4. Programming Style
C is a free-form language with a looser syntax, but a good program style and documentation will make the code easier to read and maintain.
Chapter 3rd Data
The 3rd chapter still speaks the basic knowledge of C language, mainly speaking the definition of data type.
1. C Language Data type
The data types of the C language include basic types, aggregation types, and pointer types, and the base types mainly include int,char,float,double, aggregation types include structs, arrays, enumerations, and unions, as shown in the following types:
Some of these details need to be noted:
The ANSI standard stipulates that the long type should be at least as long as the integral type, and that the integral type should be at least as long as the short integer type. The standard also specifies that the length of the long integer is at least 32 bits, the short integer is at least 16 bits, and the length of the integral type is not specified. Whether the length of the integer is 32-bit or 16-bit or 64-bit depends on the compiler. Of course, the compiler can set the length of these three types to 32 bits.
The char type was designed to accommodate character types, but it was essentially 8-bit integer data. The default char type is signed or unsigned, which is determined by the compiler. To ensure portability, char type variables should be in the intersection of signed and unsigned, which is the ASCII character set.
2. Pointer type
int *a;
Int* A;
The result of both definitions is the same, which defines a as a pointer to an int type.
However, if you want to define three pointers, the correct way is:
int *a,*b,*c; not int* a,b,c;
3. Constants
Constants are modified using const, constants are not modifiable during operation, and a constant is initialized by two methods,
One is to initialize at the time of definition;
The other is that when a function is called, a shape arguments declared as a const type is initialized to an argument
int * const p; This definition, p is a constant, the value of the pointer is immutable, but the pointer points to the content can be changed;
int const * A; This definition, *p is a constant, the value of the pointer can be changed, but the content of the pointer is not changed;
The meanings of these two definitions are different
4. Scope
There are four types of scopes for an identifier:
-File scope:
-code block scope:
-function Scope: The identifier after the goto statement
-Prototype Scope: Parameter name in function declaration
5. Static keyword
There are two uses of the static keyword,
When modifying global variables and functions, changing their link properties is not accessible outside the file;
When modifying local variables, the storage type is changed, and the storage of the stack space becomes the global space storage.
In C + +, static can turn a member variable of a class into a static member variable.
6. Implicit type conversion
For arithmetic operations (add, subtract, multiply, divide, take and sign operations), different types of strokes must be converted to the same type of data in order to operate, and the arithmetic conversion principle is:
Integer lift: For all types smaller than int, including Char, signed char, unsigned char, short, unsigned short, first promoted to int type.
In the case of an operation, the longest type in the expression is dominated, and the other type bits are converted to that type, such as:
(1) If there is a double or float in the operand, the other type of data is converted to a double type for operation.
(2) If the longest type in the operand is long. The other types are converted to a long type number.
(3) If the longest type in the operand is int, the char type is also converted to type int for operation. The arithmetic conversion is done automatically during the operation.
(4) If the longest type in the operand contains signed and unsigned int,signed will be converted to unsigned.
(5) If the longest type in the operand contains signed long int and unsigned long int,signed will be converted to unsigned.
(6) If the longest type in the operand contains float and double,float, it will be converted to double.
(7) If the longest type in the operand contains a double and a long double,double will be converted to a long double.
(8) Arithmetic operations in C are always performed with the precision of the default integer, and the character types and short integers in the expression are promoted before use, such as
Char a,b,c;
A=b+c;
B and C are promoted to integral type, and then the addition operation is performed, the result of the operation is truncated and assigned to C
When you perform an assignment, the data type to the right of the assignment operator must be converted to the type on the left of the assignment number, or truncated or rounded if the right data type is longer than the left.
Note: In the case of automatic type conversion, if the original number is an unsigned number, then at the time of expansion, the high-fill is 0; The extension is independent of the data type of the converted number.
Example:
unsigned char c=0xff;int a;unsigned int b;a=c;b=c;运行结果:a=0xff,b=0xffchar c=0xff;int a;unsigned int b;a=c;b=c;运行结果:a=0xffffffff,b=0xffffffff
4th Chapter Statement
The 4th chapter still speaks the basic knowledge of C language, mainly speaking statements.
1. printf return value
The printf function actually has a return value, which is what MSDN says:
Return Values
Each of these functions returns the number of characters printed, or a negative value if an error occurs.
The return value is the number of characters printed.
In fact, the sprintf function also has a return value, which is the number of bytes written to buffer.
2. For statement
for (Expression1,expression2,expression3)
Statement
Expression1: Initialization section, executed once before the loop body executes
Expression2: Conditional part, executed before each execution of the loop body
Expression3: Adjustment section, after the completion of the loop body, the condition part of each execution before executing
The break statement and the continue statement can be used in a for statement.
3. Switch statement
Each case label must have a unique constant value or constant expression that can be evaluated during compilation.
The continue statement can be used in a switch statement, but without any effect.
Again, do not miss the break statement after the case statement.
5th. Operators and Expressions 1, shift
The ANSI standard indicates that the shift of the unsigned number is a logical shift, and whether the shift of the signed number is a logical shift or an arithmetic shift is determined by the compiler.
The arithmetic shift retains the sign bit of the operand.
2. Expression
The assignment operator is x=y=a+3 from right-to-left, and is translated into two statements by the compiler, y=a+3;x=y; it is legal to write. However, the evaluation order of the assignment operator does not stipulate that the compiler can evaluate the value of the expression on the left side of the operator first, or the value of the expression on the right side of the operator. Therefore, *p++=*p++, such statements may get different results using different compilers.
Commas can synthesize multiple statements, such as
while(x<y) x=2,y=3;
It's legal, but it's not a good way to write.
An array of subscript references and indirect access expressions are equivalent, a[subscript]=* (A + subscript);
3. Boolean variables
C language does not have the display of Boolean tired, so with integers instead of Boolean type: 0 is false, any non 0 is true, "1" This value is not more than the other non-0 is true.
4, left value and right value
Left and right values
Lvalue: Something that can appear to the left of the assignment operator;
Right value: something that can appear to the right of the assignment operator;
An lvalue can be an rvalue, and a right-hand value is not necessarily an lvalue.
A variable can be an lvalue, and an expression that contains subscript references and indirect access can be left-valued.
6th Chapter Pointers
Pointers are the essence of the C language, with great flexibility and the most prone to problems. For beginners, pointers are difficult to understand and master. Even for an experienced program ape, using good pointers is not an easy task. The mastery of the pointer has already been tested by a procedural ape's touchstone.
The essence of a pointer is a variable, and the value stored in the variable is interpreted as a memory address. This memory address can point to a different data type, such as a char type, an int type or a float type, or even a pointer type.
For fixed-schema CPUs, the length of the pointer variable is fixed, and the length of the pointer variable is 4 on the x86 computer. This is also the basis for the powerful flexibility of pointers and the basis for pointer coercion type conversions.
For the CPU, the data stored in the memory address is 0, 1 such as the bits, as long as the length is 1 bytes, 2 bytes or 4 bytes, is completely determined by the program developer. Like what:
int *a=100;char *b=(char*)a;//a和c指向同一个内存地址,在解引用时*a访问的是4个字节,*c访问的是一个字节int c;char d;c=*a; //对应汇编语言 mov c,DWORD PTR [a]d=*b; //对应汇编语言 movsb b,DWORD PTR [b]
The pointer can perform arithmetic operations.
The pointer can be added to an integer, and after an integer, the value of the pointer moves the appropriate length, such as:
int *a,*b;b=a;a+=1;//此时b-a=sizeof(int)
Two pointers pointing to the same data type can be subtracted. Program apes should ensure that both pointers point to the same array or to the memory requested by malloc, otherwise the result is meaningless.
The pointer should be initialized before use and determine if it is a null pointer. Dereferencing a null pointer can cause a program to crash in most operating systems and will cause a potential bug if the program does not crash.
Declaring a pointer does not automatically allocate the appropriate memory.
Again, *p++ is equivalent to * (p++).
7th. Function 1, function definition and function declaration
The function definition is the function body, and the function body is implemented in the code block. The function can have a return value, or it can have no return value, and the return value can also be discarded.
A function declaration is provided to the compiler, providing information about the number of arguments and the type of the parameter, the number of arguments passed by the function call during compilation, and whether the type of each parameter matches the function declaration strictly, and the inconsistency is an error.
The scope of a function declaration is the same as the scope of a variable, which can be a file scope or a code block scope. To prevent inconsistencies in multiple copies of a function declaration, it is common to place the declaration of the function prototype in a header file, including the header file with the Include function, and modify a function declaration if it is modified. This can improve the maintainability and programming efficiency of your code.
2. Function parameters
There are two ways to pass a parameter when a function call
Call to value: The called function obtains a copy of the argument, and the read and write operation of the parameter is the operation of the copy, so the parameter cannot change the argument. Looking at the disassembly code, you can see that the parameter passing process is implemented with a stack, with a push statement that takes the arguments into the stack so that the arguments and formal parameters have different memory addresses.
Invocation: As the name implies, the address of the variable is passed in, and the variable's address is used to dereference the variable, and the value of the argument can be modified. If the passed parameter is a data name, copy the array name, it is reasonable to say that the array name should represent the entire array, but in fact the array name represents the address of the first element of the data, and the pointer is equivalent, so passing the array parameter does not copy the data, degenerate into a call to the address.
3. Recursion
Recursive function: A function that calls itself directly or indirectly within a function.
After understanding the recursive function, the easiest way to read the recursive function is not to dwell on its execution, but to believe that the recursive function will accomplish the task successfully.
In textbooks, there are two examples of recursive functions, namely the calculation of factorial and Fibonacci sequences, with recursive functions implemented by the following code:
unsigned int factorial(unsigned int n){ if (n==0 || n==1) { return 1; } return n*factorial(n-1);}unsigned int fibonacci(unsigned int n){ if (n==0) { return 0; } else if (n==1) { return 1; } return fibonacci(n-1)+fibonacci(n-2);}
There is no superiority in using recursion when calculating factorial, and recursive computation of Fibonacci sequences results in a large number of repetitive computations and inefficiencies.
"C and Pointers" lists a very interesting example of converting an integer value into a string to print out
The idea is to divide this integer value by 10, add the remainder to the 0x30, and sequentially get the characters from the bit to the highest, but this prints the reverse display, using recursion to solve the problem, and for simplicity, suppose the input data is an unsigned number
void myitoa(unsigned int n){ unsigned int quotient; quotient=n/10; if (quotient) { myitoa(quotient); } printf("%d",n%10);}
Tail recursion: If the last statement executed by the recursive function body is called itself, this function is called the tail recursion.
The tail recursion can be converted to a loop implementation, and the efficiency is usually higher. Because most compilers implement recursive functions through the run-time stack, recursive calls take up a lot of stack space compared to the loop implementation method.
The two recursive functions that compute the factorial and Fibonacci sequences are the tail recursion, with the code for the Loop implementation as follows:
unsigned int factorial(unsigned int n){ unsigned int result=1; if (n==0 || n==1) { return 1; } while(n) { result*=n--; } return result;}unsigned int fibonacci(unsigned int n){ unsigned int result=0; unsigned int prev,prevprev,i; if (n==0) { return 0; } else if (n==1) { return 1; } prev=1; prevprev=0; i=2; while(i++<=n) { result=prev+prevprev; prevprev=prev; prev=result; } return result;}
8th Chapter 1, the nature of array names
What does the array name represent? The logical answer is to represent the entire array, which is not the case, in the C language, the array name represents a pointer constant, which is the address of the first element.
2. The difference between an array and a pointer
- When the array name is used in an expression, the compiler generates a pointer constant for it, noting that it is a pointer constant. So the array name cannot be an lvalue, which is one of the differences between the array name and the pointer.
- When the array name is used for the sizeof operator, the compiler does not produce a pointer constant for it, and sizeof returns the size of the memory space occupied by the entire array rather than the length of the pointer, which is one of the differences between the array name and the pointer.
- Declares an array in which the program allocates memory space on the stack at run time, declares a pointer, and the program does not allocate the corresponding memory space, which is another difference between a pointer and an array.
The declaration is as follows: int a[5];int *b;
*a is legal and will access the first element of array A; *b will access an indeterminate location in memory that could cause the program to terminate.
3. Array Reference method
For arrays, the subscript reference and the indirect reference are identical except for the precedence, but the indirect reference is more efficient in some cases.
4. Array parameters
- When the array name is passed as a parameter, it is actually still a call to the value. Because the array name is treated as a constant pointer by the compiler, a copy of the pointer is passed in as a transmit call.
- For an array parameter in a function, in most cases, declaring an array parameter is equal to declaring the pointer parameter.
- If there is no length declaration in the formal parameter, such as int func (int a[]), in which case the actual pointer is passed, declaring that the array parameter is equal to declaring the pointer parameter, so the parameter group can match the real parameter group of any length, but this declaration does not contain the length information, The length information needs to be passed as an explicit parameter.
- If there is a length declaration in the formal parameter, such as int func (int a[10]), the compiler checks the argument type during compilation, the argument must be defined as an integer array with a length of 10, an argument of the pointer type, or an array of not 10 length cannot be compiled. But in this case, the array length is already implied in the declaration.
- In either case, the result of sizeof (parameter group) equals sizeof (pointer).
5, array initialization
- Array initialization uses curly braces, and each value in parentheses is separated by commas;
- Incomplete initialization, where the number of values in curly braces is less than the number of array elements, array elements that do not provide an initial value are initialized to 0;
- The number of values in the curly braces cannot exceed the number of array elements, otherwise it cannot be compiled;
- If the array length is not provided in the array declaration, the compiler sets the length of the array to fit exactly the length of all initial values;
- For an array defined in a code block, the memory is allocated on the stack, which is initialized each time the code block is called, and static data can be added to the array before it is statically changed;
- For static and global arrays, the linker allocates space in the PE file, usually saved in the. Data segment, initialized only once;
- The initialization of a character array can be initialized with a string, such as Char str[]= "abcdef", using the preceding method, and in this context, "abcdef" represents an initialization list instead of a string constant, and the length of the array is 7.
6. Multidimensional arrays
- Multidimensional arrays are still essentially one-dimensional arrays, and their access can be accessed either by subscript or indirectly.
- When a multidimensional array is initialized, only the length of the first dimension can be provided by default from the initialization list, and the length of the remaining several dimensions must be explicitly provided;
- When a multidimensional array is a formal parameter, only the length of the first dimension can be omitted, and the length of the remaining several dimensions must be explicitly provided; This is because the compiler must know the length of the 2nd dimension and its subsequent dimensions in order to evaluate each subscript;
- Pointer to array declaration method: Int (*p) [10];
- How the pointer array is declared: int *p[10]; the subscript reference is higher than the priority of the indirect reference.
9th. Strings, characters, and bytes
String is a very important data type, in software development, the vast majority of software involved in the processing of strings, and string processing of code usually accounted for more than 20% of the entire project code. For beginners, the string processing process is prone to overflow problems, or there are overflow vulnerabilities.
There is no string data type displayed in C because the string is stored in a character array as a character constant, in other words, the string is an array of characters.
1. String Basics
The string ends with '/', so the string cannot appear inside the ' \ ' and '/' is not a part of the string itself.
The Strlen function returns the length of a string, and the length of the string does not include the last end of '/'. This return type is the size_t type, and size_t is defined as an unsigned integer.
Note that the following two lines of code do not function the same:
if (strlen (x) >=strlen (y))
if (strlen (x)-strlen (y) >=0)
The first line of code executes as expected, but in the second line of code, because the result of subtracting two unsigned numbers is still an unsigned number, the unsigned number is not less than 0, so the result of the IF statement is always true.
2. String function with unlimited length
The lengths are unrestricted, meaning that these functions determine the length of the string by looking for the NUL character at the end of the string, which can easily cause overflow.
This kind of function has strcpy,strcat,strcmp.
where strcpy and strcat may overflow, the two functions return a copy of the first parameter, and the return value is often ignored. The strcmp is safe.
3, Length-constrained string function
This kind of function has strncpy,strncat,strncmp.
4. String Lookup function
STRCHR STRRCHR Strstr
STRPBRK: Find where any character in a character set first appears in a string
STRSPN: Finds the number of characters that match the starting position of a string to the specified character set, up to the first mismatched character
STRCSPN: Contrary to strspn
Strtok: String splitting function that modifies the source string and cannot be re-entered
5. Character functions
ToUpper () ToLower ()
IsDigit () Isxdigit () Iscntrl () isspace () islower () Isupper () Isalpha () isalnum () ispunct () isgraph () Isprint ()
6. Memory Operation function
memcpy: If the source address and destination are coincident, the result is undefined
Memmove: function is similar to memcpy, the source address and destination address can be coincident, the internal implementation is to allocate a temporary space, copy the source data to the temporary space, and then copy from the temporary space to the destination site
Memset
memcmp
C and Pointers Learning notes