1.C Language Overview
1.1 why learn C language
1.1. 1. Characteristics of C language
1) Advantages:
- Small amount of code
- Fast execution speed
- Powerful
- Programming Freedom
2) Disadvantages:
- Long code writing cycle
- Poor portability
- Too free, inexperienced and error prone
- More dependence on platform Libraries
1.1. 2. Simplicity of C language
C language has only 32 keywords, 9 control statements and 34 operators, but it can complete countless functions:
32 keyword:
9 control statements:
34 operators:
1.2 the first C language program
1.2. 1 write C language code: Hello c
#include <stdio.h> int main() { //This is the first C language code printf("hello world\n"); return 0; }
C language source code file is an ordinary text file, but the extension must be c
1.3. 3 code analysis
1) The include header file contains:
- #Include means that the header file contains, #include < stdio h> Represents containing stdio H this header file;
- When using the C language library function, you need to include the header file corresponding to the library function in advance. For example, the printf() function is used here, and stdio H) header file;
- You can view the header file required by printf through man 3 printf;
#Difference between include < > and #include "":
- < > indicates that the system searches directly according to the directory specified by the system
- '' means that the system first looks for the header file in the path specified by '' (no written path represents the current path). If it cannot be found, it will be retrieved according to the directory specified by the system
2)main function:
- A complete C language program is composed of one and only one main() function (also known as the main function, which must be present) and several other functions (optional).
- The main function is the entrance of the C language program, and the program is executed from the main function.
3) {} parentheses, program body and code block:
- {} is called code block. A code block can have one or more statements;
- Every executable code in C language is ";" Semicolon end;
- All the # beginning lines represent precompiled instructions, and there is no semicolon at the end of the precompiled instruction line;
- All executable statements must be in code blocks;
4) Note:
- //It is called line annotation. The content of annotation is ignored by the compiler, and annotation is mainly used;
- It is to add some descriptions and explanations to the code, which is conducive to code reading / * * / called block comments;
- Block annotation is the standard annotation method of C language;
- Line annotation is borrowed from C + + language;
5)printf function:
- printf is a C language library function that outputs a string to a standard output device
- printf(“hello world\n”);// \N means enter and line feed
- return statement
- return represents the completion of the function. return represents the termination of the function;
- If int precedes the definition of main, an integer needs to be written after return; If void precedes the definition of main, there is no need to write anything after return;
- In the main function, return 0 represents successful program execution, and return -1 represents failed program execution
- int main() and void main() are the same in C language, but C + + only accepts the definition of int main
1.4 system function
1.4. Use of 1System function
#include <stdlib.h> int system(const char *command); Function: execute another external program in the already running program Parameter: external executable name Return value: Success: 0 Failed: any number
Sample code block:
#include <stdio.h> #include <stdlib.h> int main() { //system("calc"); //windows platform system("ls"); //Linux platform, header file #include < stdlib h> return 0; }
1.5 C language compilation process
1.5.1C program compilation steps
The C code is compiled into an executable program through 4 steps:
- Preprocessing: macro definition expansion, header file expansion, conditional compilation, etc., and delete comments in the code. Syntax will not be checked here;
- Compilation: check the syntax and compile the preprocessed file to generate an assembly file;
- Assembly: generate assembly file into object file (binary file)
- Link: programs written in C language need to rely on various libraries, so the libraries need to be linked to the final executable program after compilation;
1.5.2 C program compilation process
1.5.3 C program execution process
1.6 CPU internal structure and registers
1.6. 1. Differences between 64 bit and 32-bit systems
- Register is the most basic storage unit in CPU
- The CPU interacts with external devices through * * bus (address, control, data) * *. The width of the bus is 8 bits, and the CPU register is also 8 bits. Then this CPU is called 8-bit CPU
- If the bus is 32-bit and the register is 32-bit, then this CPU is a 32-bit CPU
- There is a kind of CPU whose internal register is 32 bits, but the bus is 16 bits. Quasi 32 is the CPU
- All 64 bit CPUs are compatible with 32-bit instructions, and 32-bit is compatible with 16 bit instructions, so 32-bit instructions can be recognized on 64 bit CPUs
- If a 64 bit software operating system is running on a 64 bit CPU architecture, the system is 64 bit
- If a 32-bit software operating system is run on a 64 bit CPU architecture, the system is 32-bit
- 64 bit software cannot run on a 32-bit CPU
1.6. 2. Relationship among register, cache and memory
According to the distance from the CPU, the nearest is the register, then the cache (CPU cache), and finally the memory.
During CPU calculation, first read the data to be used from the hard disk to the memory, and then read the data to be used to the register. So CPU < - > register < - > memory, which is the information exchange between them.
So why cache? Because if you often operate on the data at the same address in memory, it will affect the speed. Therefore, a cache is set between register and memory.
Because extracting from the cache is much faster than memory. Of course, the price of cache must be much higher than that of memory. Otherwise, there will be no memory in the machine.
It can be seen that from a distance: CPU < - > register < - > cache < - > memory;
1.7 assembly language
1.7. 1. C language nested assembly code in vs (understand)
```c #include <stdio.h> int main() { //Define integer variables a, b, c int a; int b; int c; a = 3; b = 4; c = a + b; printf("%d\n", c);//Output the value of c return 0;//Successfully completed } //Assembly statement below __asm { mov a, 3 //The value of 3 is placed in the memory corresponding to a mov b, 4 //The value of 4 is placed in the memory corresponding to b mov eax, a //Put the value of a memory in the eax register add eax, b //Eax and b are added, and the result is placed in eax mov c, eax //The value of eax is placed in c } printf("%d\n", c);//Output the value of c return 0;//Successfully completed }
1.7. 2 disassembly in vs (understand)
#include <stdio.h> int main() { //Define integer variables a, b, c int a; int b; int c; a = 3; b = 4; c = a + b; printf("%d\n", c);//Output the value of c return 0;//Successfully completed }
1) Set breakpoint F9
2) Select the disassembly button
3) According to assembly code analysis program
3
1.7.3 Microsoft Visual Studio
Microsoft Visual Studio (VS) is a series of development kit products of Microsoft Corporation in the United States. Vs is a basically complete development tool set. It includes most tools required in the whole software life cycle, such as UML tools, code control tools, integrated development environment (IDE), etc. the object code written is applicable to all platforms supported by Microsoft. Visual studio is the most popular integrated development environment for Windows platform applications.
-
VS common shortcut keys:
Ctrl + k,Ctrl + f (auto format code)
Ctrl + k,Ctrl + c (comment code)
Ctrl + k,Ctrl + u (uncomment code)
F9 (set breakpoint)
F5 (commissioning operation)
Ctrl + F5 (no debug run)
Ctrl + Shift + b (compile, do not run)
F10 (next debugging)
F11 (step debugging) -
C4996 error for VS2013:
Since Microsoft does not recommend using the traditional library functions scanf,strcpy,sprintf, etc. of C in VS2013, directly using these library functions will prompt C4996 error:
VS recommended belt_ S functions, such as scanf_s,strcpy_s. But these are not standard C functions.
To continue using this function, you need to add the following instructions to the source file to avoid this error prompt:
#define _CRT_SECURE_NO_WARNINGS / / this macro definition is best placed in the c the first line of the file #pragma warning(disable:4996) // Or use this
2. Data type
2.1 constants and variables
2.1. 1. 32 keywords in C language:
2.1. 2 data type
Function of data type: the amount of memory space allocated by the compiler budget object (variable).
2.1. 3 constant
Constant:
- The amount whose value cannot be changed during program operation;
- Constants generally appear in expressions or assignment statements;
- give an example:
Integer constant: 100200, - 100, 0, real constant: 3.14, 0.125, - 3.123
Character constant: 'a', 'b', '1', 'n'
String constants: "a", "ab", "12356"
2.1. 4 variables
1) Variable
Variable:
- Its value can be changed during program operation
- Variables must be defined before use, and there must be corresponding data types before defining variables
Identifier naming rules:
- Identifier cannot be a keyword
- The identifier can only be composed of letters, numbers and underscores
- The first character must be a letter or underscore
- Letters in identifiers are case sensitive
Variable characteristics:
- Variable allocates corresponding memory space for it at compile time
- The corresponding memory can be accessed by its name and address
- Difference between declaration and definition:
- There is no need to establish storage space for declaring variables, such as extern int a;
- Storage space needs to be established to define variables, such as int b;
#include <stdio.h> int main() { //The extern keyword is only a declaration and cannot be defined. We will learn about it later. Let's learn it first //Declare a variable a, where no storage space is established extern int a; a = 10; //err, no space, no assignment int b = 10; //Define a variable b, the type of b is int, and the value of b is 10 return 0; }
In a broad sense, declarations contain definitions, that is, definitions are a special case of declarations, so not all declarations are definitions:
- int b is both a declaration and a definition
- For extern b, it's just a declaration, not a definition
2.1. 5 use examples
#include <stdio.h> #define MAX 10 / / a constant is declared. The name is MAX and the value is 10. Once initialized, the value of the constant cannot be changed int main() { int a; //Defines a variable of type int called a const int b = 10; //Define a const constant named b with a value of 10 //b = 11; //err, the value of a constant cannot be changed //MAX = 100; // err, the value of a constant cannot be changed a = MAX;//Set the value of abc to the value of MAX a = 123; printf("%d\n", a); //Print the value of variable a return 0; }
2.2 integer: int
2.2. 1. Definition and output of integer variables:
Print format | meaning |
---|---|
%d | Outputs a signed decimal int type |
%O (letter o) | Output octal int type |
%x | Output hexadecimal int type, and the letters are output in lowercase |
%X | Output hexadecimal int type, and output letters in uppercase |
%u | Output a decimal unsigned number |
#include <stdio.h> int main() { int a = 123; //Define variable a and assign 123 in hexadecimal mode int b = 0567; //Define variable b and assign it as 0567 in octal mode int c = 0xabc; //Define the variable c and assign it 0xabc in hexadecimal mode printf("a = %d\n", a); printf("8 Base: b = %o\n", b); printf("10 Base: b = %d\n", b); printf("16 Base: c = %x\n", c); printf("16 Base: c = %X\n", c); printf("10 Base: c = %d\n", c); unsigned int d = 0xffffffff; //Defines the unsigned int variable d, which is assigned in hexadecimal printf("Signed printing: d = %d\n", d); printf("Unsigned printing: d = %u\n", d); return 0; }
2.2. 2 input of integer variable
#include <stdio.h> int main() { int a; printf("Please enter a Value of:"); //Do not add "\ n" scanf("%d", &a); printf("a = %d\n", a); //Print the value of a return 0; }
2.2.3 short ,int , long , long long
data type | Occupied space |
---|---|
Short (short integer) | 2 bytes |
Int (integer) | 4 bytes |
Long (long integer) | 4 bytes for Windows, 4 bytes (32 bits) for Linux, 8 bytes (64 bits) |
Long long (long integer) | 2 bytes |
be careful:
- It should be noted that the number of bytes of integer data in memory is related to the selected operating system. Although the length of integer data is not specified in the C language standard, the length of long type integers cannot be shorter than int type, and the length of short type integers cannot be longer than int type.
- When a small data type is assigned to a large data type, there will be no error, because the compiler will convert it automatically. However, when a large type is assigned to a small data type, the high bit may be lost.
2.2. 4 difference between signed number and unsigned number
- Signed number
Signed number is the highest sign bit, 0 represents positive number and 1 represents negative number.
#include <stdio.h> int main() { signed int a = -1089474374; //Define signed integer variable a printf("%X\n", a); //The result is BF0FF0BA //B F 0 F F 0 B A //1011 1111 0000 1111 1111 0000 1011 1010 return 0; }
- An unsigned number is the highest bit, not the sign bit, but a part of the number. An unsigned number cannot be negative.
#include <stdio.h> int main() { unsigned int a = 3236958022; //Define unsigned integer variable a printf("%X\n", a); //The result is C0F00F46 return 0; }
When we write programs to deal with an impossible negative value, we usually use unsigned numbers, which can increase the maximum value of the number.
3) Signed and unsigned integer value range
data type | Occupied space | Value range |
---|---|---|
short | 2 bytes | -32768 to 32767 (- 2 ^ 15 ~ 2 ^ 15-1) |
long | 4 bytes | -2147483648 to 2147483647 (- 2 ^ 31 ~ 2 ^ 31-1) |
int | 4 bytes | -2147483648 to 2147483647 (- 2 ^ 31 ~ 2 ^ 31-1) |
unsigned short | 2 bytes | 0 to 65535 (0 ~ 2 ^ 16-1) |
unsigned int | 4 bytes | 0 to 4294967295 (0 2 ^ 32-1) |
unsigned long | 4 bytes | 0 to 4294967295 (0 2 ^ 32-1) |
2.3 sizeof keyword
- sizeof is not a function, so it does not need to include any header files. Its function is to calculate the size of data types in bytes
- The return value of sizeof is size_t
- size_t type is unsigned int in 32-bit operating system, which is an unsigned integer
#include <stdio.h> int main() { int a; int b = sizeof(a);//sizeof gets the size of memory occupied by the specified value, in bytes printf("b = %d\n", b); size_t c = sizeof(a); printf("c = %u\n", c);//Output the value of c as an unsigned number return 0; }
2.4 character type: char
2.4. 1 Definition and output of character variables
- Character variables are used to store a single character, which is represented by char in C language. Each character variable will occupy 1 byte. When assigning a value to a character variable, you need to enclose the characters with a pair of single quotation marks (') in English half width format.
- In fact, the character variable does not put the character itself into the memory unit of the variable, but puts the ASCII code corresponding to the character into the storage unit of the variable. char is essentially a 1-byte integer.
#include <stdio.h> int main() { char ch = 'a'; printf("sizeof(ch) = %u\n", sizeof(ch)); printf("ch[%%c] = %c\n", ch); //Print character printf("ch[%%d] = %d\n", ch); //Print ASCII value of 'a' char A = 'A'; char a = 'a'; printf("a = %d\n", a); //97 printf("A = %d\n", A); //65 printf("A = %c\n", 'a' - 32); //Lowercase a to uppercase A printf("a = %c\n", 'A' + 32); //Capital a to lowercase a ch = ' '; printf("Empty character:%d\n", ch); //The null character ASCII value is 32 printf("A = %c\n", 'a' - ' '); //Lowercase a to uppercase A printf("a = %c\n", 'A' + ' '); //Capital a to lowercase a return 0; }
2.4. Input of 1 character variable
#include <stdio.h> int main() { char ch; printf("Please enter ch Value of:"); //Do not add "\ n" scanf("%c", &ch); printf("ch = %c\n", ch); //Printed ch aracters return 0; }
2.4.2 ASCII comparison table
ASCII code is roughly composed of the following two parts:
- ASCII non printing control characters: the numbers 0-31 on the ASCII table are assigned to the control characters, which are used to control some peripheral devices such as printers.
- ASCII printed characters: the numbers 32-126 are assigned to characters that can be found on the keyboard and appear when viewing or printing a document. The number 127 represents the Del command.
2.4. 3 escape character
Escape character | meaning | ASCII value (decimal) |
---|---|---|
\a | alert | 007 |
\b | Backspace (BS) to move the current position to the previous column | 008 |
\f | Page feed (FF) moves the current position to the beginning of the next page | 012 |
\n | Line feed (LF) moves the current position to the beginning of the next line | 010 |
\r | Press enter (CR) to move the current position to the beginning of the line | 013 |
\t | Horizontal tabulation (HT) (skip to next TAB position) | 009 |
\v | Vertical tabulation (VT) report | 011 |
\ | Represents a backslash character '' | 092 |
' | Represents a single quotation mark (apostrophe) character | 039 |
" | Represents a double quote character | 034 |
? | Represents a question mark | 063 |
\0 | Number 0 | 000 |
\ddd | Octal escape character, d range 0 ~ 7 | 3-bit octal |
\xhh | Hexadecimal escape character, h range 09, af, A~F | 3-bit hex |
2.5 real (floating point): float,double
Real variables can also be called floating-point variables, which are used to store decimal values. In C language, there are two kinds of floating-point variables: single precision floating-point number (float) and double precision floating-point number (double), but the floating-point number represented by double variable is more accurate than float variable.
Because floating-point variables are composed of a limited number of storage units, they can only provide a limited number of significant digits. Numbers outside the significant bits will be rounded off, which may cause some errors.
Constants that do not end with F are of type double, and constants that end with F (such as 3.14f) are of type float.
#include <stdio.h> int main() { //Traditional assignment float a = 3.14f; //Or 3.14F double b = 3.14; printf("a = %f\n", a); printf("b = %lf\n", b); //Scientific law assignment a = 3.2e3f; //3.2 * 1000 = 3200, e can write E printf("a1 = %f\n", a); a = 100e-3f; //100*0.001 = 0.1 printf("a2 = %f\n", a); a = 3.1415926f; printf("a3 = %f\n", a); //The result is 3.141593 return 0; }
2.6 hex
Hexadecimal system, also known as carry system, is a carry method stipulated by people. For any kind of base system - x base system, it means that the number operation at a certain position is carried into one digit every X. Decimal is every decimal one, hexadecimal is every hexadecimal one, binary is every binary one, and so on, X-ary is every x carry.
decimal system | Binary | octal number system | hexadecimal |
---|---|---|---|
0 | 0 | 0 | 0 |
1 | 1 | 1 | 1 |
2 | 10 | 2 | 2 |
3 | 11 | 3 | 3 |
4 | 100 | 4 | 4 |
5 | 101 | 5 | 5 |
6 | 110 | 6 | 6 |
7 | 111 | 7 | 7 |
8 | 1000 | 10 | 8 |
9 | 1001 | 11 | 9 |
10 | 1010 | 12 | A |
11 | 1011 | 13 | B |
12 | 1100 | 14 | C |
13 | 1101 | 15 | D |
14 | 1110 16 | E | |
15 | 1111 | 17 | F |
16 | 10000 20 | 10 |
2.61 binary
Binary is a number system widely used in computing technology. Binary data is a number represented by two numbers: 0 and 1. Its cardinality is 2, the carry rule is "every two into one", and the borrow rule is "borrow one when two".
The current computer system basically uses binary system, and the data is mainly stored in the form of complement in the computer.
term | meaning |
---|---|
Bit (bit) | A binary represents a bit, and a bit can only represent two states: 0 or 1. Data transmission is customary in "bits". |
Byte (bytes) | A Byte is 8 binary, called 8 bits. The smallest unit stored in the computer is Byte. Data storage is customary in bytes. |
Word (double byte) | 2 bytes, 16 bits |
DWORD | Two words, 4 bytes, 32 bits |
1b | 1 bit, 1 bit |
1B | 1Byte,1 byte, 8 bits |
1k,1K | 1024 |
1m (1MB) | 1024k, 1024*1024 |
1G | 1024M |
1T | 1024G |
1KB (thousands) | 1024bit,1024 bits |
1KB (kilobytes) | 1024Byte, 1024 bytes |
1MB (megabit) | 1024Kb = 1024 * 1024bit |
1MB (megabytes) | 1024KB = 1024 * 1024Byte |
The method of converting decimal to binary: divide decimal by 2 and take the remainder and quotient respectively. When the quotient is 0, the result of conversion is to reverse the remainder.
Decimal decimal is converted into binary: the decimal part is multiplied by 2 and takes an integer, less than 1 takes 0, and each multiplication is the decimal part. In order, the number after rounding is the result of conversion.
2.6. 2 octal
Octal, octal, abbreviated OCT or O, is a counting method based on 8. It adopts eight digits of 0, 1, 2, 3, 4, 5, 6 and 7, and enters 1 every eight. Some programming languages often start with the number 0 to indicate that the number is octal.
Octal numbers and binary numbers can correspond by bit (octal one bit corresponds to binary three bits), so they are often used in computer languages.
Method of converting decimal to octal:
Divide the decimal number by 8 and take the remainder and quotient respectively. When the quotient is 0, inverting the remainder is the result of conversion.
2.6. 3 hex
Hexadecimal (English Name: hexadecimal) is different from the representation in our daily life. It is composed of 0-9 and A-F, and the letters are case insensitive. The corresponding relationship with hexadecimal is: 0-9 corresponds to 0-9, and A-F corresponds to 10-15.
Hexadecimal numbers and binary numbers can correspond by bit (one hexadecimal bit corresponds to four binary bits), so they are often used in computer languages.
How to convert decimal to hexadecimal:
Divide the decimal number by 16 and take the remainder and quotient respectively. When the quotient is 0, inverting the remainder is the result of conversion.
2.6. 4 how to express the corresponding hexadecimal number in C language
Base system | form |
---|---|
decimal system | Start with normal numbers 1-9, such as 123 |
octal number system | Start with the number 0, such as 0123 |
hexadecimal | Start with 0x, e.g. 0x123 |
Binary | C language cannot write binary numbers directly |
#include <stdio.h> int main() { int a = 123; //Decimal assignment int b = 0123; //Octal assignment, starting with the number 0 int c = 0xABC; //Hexadecimal assignment //If you output a decimal number in printf, use% d, octal% o, and hexadecimal% x printf("decimal system:%d\n",a ); printf("octal number system:%o\n", b); //%o. Is a letter O, not a number printf("hexadecimal:%x\n", c); return 0; }
2.7 computer memory value storage mode
2.7. 1 original code
The original code of a number (original binary code) has the following characteristics:
- The highest bit is the sign bit, 0 means positive and 1 means negative
- The other numerical part is the binary number of the absolute value of the numerical value itself
- The original code of a negative number is based on its absolute value, and the highest bit becomes 1
The following values are described in 1 byte size:
Decimal number | Original code |
---|---|
+15 | 0000 1111 |
-15 | 1000 1111 |
+0 | 0000 0000 |
-0 | 1000 0000 |
The representation of the original code is simple and easy to understand. It is easy to convert with the signed number itself. As long as the symbol is restored, but when two positive numbers are subtracted or different symbol numbers are added, the absolute value of the two numbers must be compared to determine who is subtracted and whether the result is positive or negative. Therefore, the original code is not convenient for addition and subtraction.
2.7. 2 inverse code
- For positive numbers, the inverse code is the same as the original code
- For negative numbers, the sign bit remains unchanged, and other parts are reversed (1 becomes 0, 0 becomes 1)
Decimal number | Inverse code |
---|---|
+15 | 0000 1111 |
-15 | 1111 0000 |
+0 | 0000 0000 |
-0 | 1111 1111 |
Inverse code operation is also inconvenient. It is usually used as an intermediate transition for finding complement.
2.7. 3 Complement
In the computer system, all values are stored by complement.
Complement features:
- For positive numbers, the original code, inverse code and complement code are the same
- For a negative number, its complement is its inverse plus 1
- The complement symbol bit is fixed, the other bits are reversed, and finally the whole number is added by 1 to obtain the original code
Decimal number | Complement |
---|---|
+15 | 0000 1111 |
-15 | 1111 0001 |
+0 | 0000 0000 |
-0 | 0000 0000 |
#include <stdio.h> int main() { int a = -15; printf("%x\n", a); //The result is fffff1 //Binary corresponding to fffff1: 1111 1111 1111 1111 1111 1111 0001 //The sign bit remains unchanged, and others are reversed: 1000 0000 1110 //Add 1:1000 0000 0000 0000 1111 to the top. The highest 1 represents a negative number, which is - 15 return 0; }
2.7. 4 the meaning of complement
Example 1: use 8-bit binary numbers to represent + 0 and - 0 respectively
Decimal number | Original code |
---|---|
+0 | 0000 0000 |
-0 | 1000 0000 |
Decimal number | Inverse code |
---|---|
+0 | 0000 0000 |
-0 | 1111 1111 |
Whether stored in the original code or in the inverse code, 0 can also be expressed in two forms. Why does the same 0 have two different representations?
However, if stored in complement, the complement unifies the coding of zero:
Decimal number | Complement |
---|---|
+0 | 0000 0000 |
-0 | Since only 8 bits are used to describe 10000 0000, the highest bit 1 is discarded and becomes 0000 0000 |
Example 2: results of calculation 9-6
Add in original code:
Decimal number | Original code |
---|---|
9 | 0000 1001 |
-6 | 1000 0110 |
The result is - 15, incorrect.
Add by complement:
Decimal complement
9 |0000 1001
-6 |1111 1010
The highest bit 1 overflows, and the remaining 8 bits represent 3, which is correct.
In the computer system, all values are stored by complement, mainly because:
- Unified zero coding
- Unified processing of symbol bits and other bits
- Convert subtraction to addition
- When two numbers represented by complement are added, if the highest bit (sign bit) has carry, the carry is discarded
2.7. 5 value overflow
When more than one data type can hold the maximum range, the value will overflow.
The difference between the overflow of the highest bit of the signed bit: the overflow of the signed bit will change the positive and negative of the number, but the overflow of the highest bit will lead to the loss of the highest bit.
data type | Occupied space | Value range |
---|---|---|
char | 1 byte | -128 to |
unsigned char | 1 byte | 0 to 255 (0 ~ 28-1) |
#include <stdio.h> int main() { char ch; //Symbol bit overflow will change the positive and negative of the number ch = 0x7f + 2; //127+2 printf("%d\n", ch); // 0111 1111 //+2 after 1000 0001, this is a negative complement, the original code is 1111 1111, and the result is - 127 //Overflow of the highest bit will result in loss of the highest bit unsigned char ch2; ch2 = 0xff+1; //255+1 printf("%u\n", ch2); // 1111 1111 //+After 1, there is only 8-bit overflow in char. The result is 0000 0000 and the decimal system is 0 ch2 = 0xff + 2; //255+1 printf("%u\n", ch2); // 1111 1111 //+After 10000 0001, char only overflows the highest bit of 8 bits. The result is 0000 0001 and the decimal system is 1 return 0; }
2.8 type qualifier
qualifier | meaning |
---|---|
extern | Declare a variable. The variable declared by extern does not establish storage space. extern int a;// Variables create storage space when they are defined |
const | Define a constant whose value cannot be modified. const int a = 10; |
Volatile | Prevent compiler from optimizing code |
register | Define register variables to improve efficiency. Register is a recommended instruction, not a command instruction. If the CPU has free registers, the register will take effect. If there are no free registers, the register will be invalid. |
2.9 string format output and input
2.9. 1 string constant
- A string is a continuous char space in memory, ending with '\ 0' (number 0).
- String constants are character sequences enclosed in double quotation marks, such as "china", "C program", "$12.5", etc. are legal string constants.
- Differences between string constants and character constants:
- At the end of each string, the compiler will automatically add an end flag bit '\ 0', that is, "a" contains two characters' a 'and' \ 0 '.
2.9.2 printf function and putchar function
- printf outputs a string and putchar outputs a char.
printf format characters:
Print format | Corresponding data type | meaning |
---|---|---|
%d | int | Accepts an integer value and represents it as a signed decimal integer |
%hd | short int | Short integer |
%hu | unsigned short | Unsigned short integer |
%o | unsigned int | Unsigned octal integer |
%u | unsigned int | Unsigned decimal integer |
%x,%X | unsigned int | Unsigned hexadecimal integer, X corresponds to ABCDEF, and X corresponds to ABCDEF |
%f | float | Single-precision floating-point |
%lf | double | Double precision floating point number |
%e,%E | double | The number represented by scientific counting. The case of "e" here represents the case of "e" used in output |
%c | char | character. The input numbers can be converted into corresponding characters according to ASCII code |
%s | char * | character string. Output the characters in the string until the empty characters in the string (the string ends with '\ 0', which is the empty character) |
%p | void * | Output pointer in hexadecimal form |
%% | % | Output a percent sign |
printf additional format:
character | meaning |
---|---|
L (letter l) | Append before d,u,x,o to indicate long integer left alignment |
M (represents an integer) | Minimum data width |
0 (number 0) | Fill the front of the output with 0 until it occupies the specified column width. It cannot be used together- |
m. N (represents an integer) | m refers to the field width, that is, the number of characters occupied by the corresponding output item on the output device. N refers to the precision, which is used to describe the decimal places of the output real number. For numeric, when n is not specified, the implied precision is n=6 bits. |
#include <stdio.h> int main() { int a = 100; printf("a = %d\n", a);//Format output a string printf("%p\n", &a);//Address number of output variable a in memory printf("%%d\n"); char c = 'a'; putchar(c);//putchar has only one parameter, which is the char to be output long a2 = 100; printf("%ld, %lx, %lo\n", a2, a2, a2); long long a3 = 1000; printf("%lld, %llx, %llo\n", a3, a3, a3); int abc = 10; printf("abc = '%6d'\n", abc); printf("abc = '%-6d'\n", abc); printf("abc = '%06d'\n", abc); printf("abc = '%-06d'\n", abc); double d = 12.3; printf("d = \' %-10.3lf \'\n", d); return 0; }
2.9.3 scanf function and getchar function
- getchar reads a char from a standard input device.
- scanf can get the data entered by the user through the standard input device by% escape.
#include <stdio.h> int main() { char ch1; char ch2; char ch3; int a; int b; printf("Please enter ch1 Characters:"); ch1 = getchar(); printf("ch1 = %c\n", ch1); getchar(); //Test the function of getchar() here printf("Please enter ch2 Characters:"); ch2 = getchar(); printf("\'ch2 = %ctest\'\n", ch2); getchar(); //Test the function of getchar() here printf("Please enter ch3 Characters:"); scanf("%c", &ch3);//The second parameter here must be the address of the variable, not the variable name printf("ch3 = %c\n", ch3); printf("Please enter a Value of:"); scanf("%d", &a); printf("a = %d\n", a); printf("Please enter b Value of:"); scanf("%d", &b); printf("b = %d\n", b); return 0; }
3. Operators and expressions
3.1 classification of common operators
Operator type | effect |
---|---|
Arithmetic operator | Used to process four operations |
Assignment Operators | Used to assign the value of an expression to a variable |
Comparison operator | Used to compare expressions and return a true or false value |
Logical operator | Used to return true or false values based on the value of an expression |
Bitwise Operators | Bit operation for processing data |
sizeof operator | Used to find the length of bytes |
3.2 arithmetic operators
operator | term | Example | result |
---|---|---|---|
+ | Plus sign | +3 | 3 |
- | minus sign | -3 | -3 |
+ | plus | 10 | + 5 |
- | reduce | 10 | - 5 |
* | ride | 10 * 5 | 50 |
/ | except | 10 / 5 | 2 |
% | Mold taking (residual) | 10 % 3 | 1 |
++ | Pre autoincrement | a=2; b=++a; | a=3; b=3; |
++ | Post autoincrement | a=2; b=a++; | a=3; b=2; |
– | Front self subtraction | a=2; b=–a; | a=1;b=1; |
– | Post subtraction | a=2; b=a–; | a=1;b=2; |
3.3 assignment operator
operator | term | Example | result |
---|---|---|---|
= | assignment | a=2; b=3; | a=2; b=3; |
+= | Plus equals | a=0; a+=2; | a=2; |
-= | Minus equals | a=5; a-=3; | a=2; |
*= | Multiply equal | a=2; a*=2; | a=4; |
/= | Division equals | a=4; a/=2; | a=2; |
%= | Modulo equal | a=3; a%2; | a=1; |
3.4 comparison operators
In the comparison operation of C language, "true" is represented by the number "1" and "false" by the number "0".
operator | term | Example | result |
---|---|---|---|
== | Equal to | 4 == 3 | 0 |
!= | Not equal to | 4 != 3 | 1 |
< | less than | 4 < 3 | 0 |
> | greater than | 4 > 3 | 1 |
<= | Less than or equal to | 4 <= 3 | 0 |
>= | Greater than or equal to | 4 >= 1 | 1 |
3.5 logical operators
operator | term | Example | result |
---|---|---|---|
! | wrong | !a | If a is false, then! A is true; If a is true, then! A is false. |
&& | And | a && b | If both a and b are true, the result is true, otherwise it is false. |
or | a |
3.6 operator priority
3.7 type conversion
There are different types of data, and the problem of type conversion must be involved in the mixed operation between different types of data.
There are two methods of conversion:
- Automatic conversion (implicit conversion): it is automatically completed by the compilation system following certain rules.
- Cast: cast the operation result of an expression to the required data type.
Principle of type conversion: the type with less memory bytes (small value range) shall be converted to the type with more memory bytes (large value range) to ensure that the accuracy will not be reduced.
3.7. 1 implicit conversion
#include <stdio.h> int main() { int num = 5; printf("s1=%d\n", num / 2); printf("s2=%lf\n", num / 2.0); return 0; }
3.7. 2 forced conversion
Cast type conversion refers to converting a variable or expression into the required type using cast type conversion operator. Its basic syntax format is as follows:
(type specifier) (expression)
#include <stdio.h> int main() { float x = 0; int i = 0; x = 3.6f; i = x; //x is a real type and i is an integer type. If you assign a value directly, there will be a warning i = (int)x; //Use cast printf("x=%f, i=%d\n", x, i); return 0; }
4. Procedure flow structure
4.1 General
C language supports three basic program running structures: sequential structure, selection structure and loop structure.
- Sequence structure: the program is executed in sequence without jump.
- Select structure: perform corresponding functions selectively according to whether the conditions are met.
- Loop structure: execute a piece of code multiple times according to whether the conditions are met.
4.2 selection of structure
4.2.1 if statement
#include <stdio.h> int main() { int a = 1; int b = 2; if (a > b) { printf("%d\n", a); } return 0; }
4.2. 2. If... else statement
#include <stdio.h> int main() { int a = 1; int b = 2; if (a > b) { printf("%d\n", a); } else { printf("%d\n", b); } return 0; }
4.2.3 if... else if... else statements
#include <stdio.h> int main() { unsigned int a; scanf("%u", &a); if (a < 10) { printf("Bit\n"); } else if (a < 100) { printf("Ten\n"); } else if (a < 1000) { printf("Hundredth\n"); } else { printf("great\n"); } return 0; }
4.2. 4 ternary operator
#include <stdio.h> int main() { int a = 10; int b = 20; int c; if (a > b) { c = a; } else { c = b; } printf("c1 = %d\n", c); a = 1; b = 2; c = ( a > b ? a : b ); printf("c2 = %d\n", c); return 0; }
4.2.5 switch statement
Basic usage of switch statement:
-
When executing the program, first calculate the value of the expression and compare it with the constant expression value after case. If it is equal, execute the statement block of the corresponding part. After execution, use the break statement to jump out of the switch branch statement. If the value of the expression does not match the constant expression after all cases, execute the statement n corresponding to the default item, and jump out of the switch branch statement after execution.
-
The constant expression after case can only be one of integer, character or enumeration constants; The value of each case statement expression is different, and only plays the role of a label, which is used to guide the program to find the corresponding entry.
-
The statement block here can be a statement or other compound statements. Statement blocks may not use curly braces' {} '.
-
Each case statement is not the end point of program execution. It is usually necessary to execute a break statement to jump out of the switch branch statement; If there is no break statement after the statement block of a case statement is executed, other case statements will be executed in sequence until the break statement is encountered or all subsequent case statements are executed, and then the switch branch statement will jump out.
-
Multiple case s can share a set of execution statement blocks.
-
The order of occurrence of each case and default does not affect the execution result.
-
The default statement is not required, but it is recommended to add it as the default processing item.
-
The switch statement only performs equality detection, not relational expression or logical expression calculation like the if statement, so as to judge whether the logic is true or false.
#include <stdio.h> int main() { char c; c = getchar(); switch (c) //Parameters can only be integer variables { case '1': printf("OK\n"); break;//The switch is interrupted when it encounters a break case '2': printf("not OK\n"); break; default://If none of the above conditions are met, execute default printf("are u ok?\n"); } return 0; }
4.3 circulation structure
4.3. 1. While statement
#include <stdio.h> int main() { int a = 20; while (a > 10) { scanf("%d", &a); printf("a = %d\n", a); } return 0; }
4.3. 2. Do... while statement
Note that in the do while structure, the semicolon after the while bracket cannot be lost.
The execution process of the do while loop is to unconditionally execute the loop body once, and then judge whether to continue executing the loop body according to the value of the loop control expression. If true, continue; If false, stop execution and exit the do while loop. That is, the do while loop executes the loop body at least once.
The main difference between a do while loop and a while loop is that the former executes the loop body at least once, while the latter may not execute the loop body at all.
#include <stdio.h> int main() { int a = 1; do { a++; printf("a = %d\n", a); } while (a < 10); return 0; }
4.3.3 for statement
-
The general form of the for statement is: for (single expression; conditional expression; end loop body) {intermediate loop body;}
-
When the for loop executes:
- First judge whether the conditional expression is true
- If the condition holds, the intermediate loop body is executed, and then the end loop body is executed after the intermediate loop body is executed
- After executing the end loop body, judge the conditional expression again. If the condition is still valid, continue to repeat the intermediate loop body. If the condition is not valid, jump out of the for loop
- The intermediate loop body executed in the for loop can be one statement or multiple statements. When there is only one statement in the intermediate loop body, its braces {} can be omitted
#include <stdio.h> int main() { int i; int sum = 0; for (i = 0; i <= 100; i++) { sum += i; } printf("sum = %d\n", sum); return 0; }
4.3. 4 nested loop
Loop statements can be nested with each other:
#include <stdio.h> int main() { int num = 0; int i, j, k; for (i = 0; i < 10; i++) { for (j = 0; j < 10; j++) { for (k = 0; k < 10; k++) { printf("hello world\n"); num++; } } } printf("num = %d\n", num); return 0; }
4.4 jump statements break, continue, goto
4.3.1 break statement
break statements can be used in both switch conditional statements and loop statements:
-
When it appears in the switch conditional statement, its function is to terminate a case and jump out of the switch structure.
-
When it appears in a loop statement, its function is to jump out of the current inner loop statement and execute the following code. When it appears in a nested loop statement, it jumps out of the nearest inner loop statement and executes the following code.
#include <stdio.h> int main() { int i = 0; while (1) { i++; printf("i = %d\n", i); if (i == 10) { break; //Jump out of while loop } } int flag = 0; int m = 0; int n = 0; for (m = 0; m < 10; m++) { for (n = 0; n < 10; n++) { if (n == 5) { flag = 1; break; //Jump out of for (n = 0; n < 10; N + +) } } if (flag == 1) { break; //Jump out of for (M = 0; m < 10; m + +) } } return 0; }
4.3.2 continue statement
In a loop statement, if you want to terminate this loop immediately and execute the next loop, you need to use the continue statement.
#include<stdio.h> int main() { int sum = 0; //Define variable sum for (int i = 1; i <= 100; i++) { if (i % 2 == 0) //If i is an even number, execute the code in the if statement { continue; //End this cycle } sum += i; //Realize the accumulation of sum and i } printf("sum = %d\n", sum); return 0; }
4.3.3 goto statement (unconditional jump, use as little as possible)
#include <stdio.h> int main() { goto End; //ID of unconditional jump to End printf("aaaaaaaaa\n"); End: printf("bbbbbbbb\n"); return 0; }
5. Arrays and strings
5.1 general
In programming, in order to facilitate data processing, several variables of the same type are organized in an orderly form - called arrays.
An array is a continuous variable space of the same type in memory. All members of the same array are of the same data type, and the addresses of all members in memory are continuous.
Array is of construction data type:
- An array can be decomposed into multiple array elements: these array elements can be basic data types or construction types.
int a[10]; struct Stu boy[10];
- According to different types of array elements, arrays can be divided into: numerical array, character array, pointer array, structure array and so on.
- int a[10]; - char s[10]; char *p[10];
Generally, the number of subscripts of array elements is also called dimension. According to different dimensions, arrays can be divided into one-dimensional array, two-dimensional array, three-dimensional array, four-dimensional array, etc. Generally, we call two-dimensional and above arrays multidimensional arrays.
5.2 one dimensional array
5.2. 1 Definition and use of one-dimensional array
- The array name meets the writing requirements of the identifier (number, English letter, underscore)
- The array name cannot be the same as other variable names. It is unique in the same scope
- The constant expression in square brackets [] indicates the number of array elements
int a[3] indicates that array a has 3 elements
The subscript is calculated from 0, so the three elements are a[0],a[1],a[2]
- When defining an array, it is better to use constants in []. When using an array, it can be either constants or variables
#include <stdio.h> int main() { int a[10];//Defines an array called a with 10 members, each of which is of type int //a[0]... a[9], no a[10] //Without a variable, a is the name of the array, but not the variable name. It is a constant a[0] = 0; //...... a[9] = 9; int i = 0; for (i = 0; i < 10; i++) { a[i] = i; //Assign a value to an array } //Traverse the array and output the value of each member for (i = 0; i < 10; i++) { printf("%d ", a[i]); } printf("\n"); return 0; }
5.2. 2 initialization of one-dimensional array
It is called initialization to assign values while defining an array. If the global array is not initialized, the compiler initializes it to zero. If the local array is not initialized, the contents are random values.
int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };//Define an array and initialize all member variables at the same time int a[10] = { 1, 2, 3 };//Initialize the first three members and set all subsequent elements to 0 int a[10] = { 0 };//All members are set to 0 //The number of elements is not defined in [] and must be initialized when defining int a[] = { 1, 2, 3, 4, 5 };//Defines an array with 5 members
5.2. 3 array name
The array name is an address constant that represents the address of the first element in the array.
#include <stdio.h> int main() { int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };//Define an array and initialize all member variables at the same time printf("a = %p\n", a); printf("&a[0] = %p\n", &a[0]); int n = sizeof(a); //Memory size of array, 10 int types, 10 * 4 = 40 int n0 = sizeof(a[0]);//The memory size occupied by the 0th element of the array, and the 0th element is int, 4 int i = 0; for (i = 0; i < sizeof(a) / sizeof(a[0]); i++) { printf("%d ", a[i]); } printf("\n"); return 0; }
5.2. 4 intensive training
- Maximum value of one-dimensional array
#include <stdio.h> int main() { int a[] = { 1, -2, 3,- 4, 5, -6, 7, -8, -9, 10 };//Define an array and initialize all member variables at the same time int i = 0; int max = a[0]; for (i = 1; i < sizeof(a) / sizeof(a[0]); i++) { if (a[i] > max) { max = a[i]; } } printf("The maximum value in the array is:%d\n", max); return 0; }
- Inverse of one-dimensional array
#include <stdio.h> int main() { int a[] = { 1, -2, 3,- 4, 5, -6, 7, -8, -9, 10 };//Define an array and initialize all member variables at the same time int i = 0; int j = sizeof(a) / sizeof(a[0]) -1; int tmp; while (i < j) { tmp = a[i]; a[i] = a[j]; a[j] = tmp; i++; j--; } for (i = 0; i < sizeof(a) / sizeof(a[0]); i++) { printf("%d ", a[i]); } printf("\n"); return 0; }
- bubble sort
Illustration:
#include <stdio.h> int main() { int a[] = { 1, -2, 3,- 4, 5, -6, 7, -8, -9, 10 };//Define an array and initialize all member variables at the same time int i = 0; int j = 0; int n = sizeof(a) / sizeof(a[0]); int tmp; //1. Process //2. Number of trials for (i = 0; i < n-1; i++) { for (j = 0; j < n - i -1 ; j++)//The purpose of the inner loop is to compare adjacent elements and put the large one behind { if (a[j] > a[j + 1]) { tmp = a[j]; a[j] = a[j+1]; a[j+1] = tmp; } } } for (i = 0; i < n; i++) { printf("%d ", a[i]); } printf("\n"); return 0; }
5.3 two dimensional array
5.3. 1 Definition and use of two-dimensional array
The general form of two-dimensional array definition is:
Type specifier array name [constant expression 1] [constant expression 2]
Where constant expression 1 represents the length of the first dimensional subscript and constant expression 2 represents the length of the second dimensional subscript.
int a[3][4];
- The naming rule is the same as that of one-dimensional array
- Defines an array with three rows and four columns. The array name is a, its element type is integer, and the number of elements of the array is 3 × 4, i.e.:
The two-dimensional array A is stored by row, first storing row a[0], then storing row a[1] and row a[2], and each row has four elements, which are stored in turn.
- A two-dimensional array is conceptually two-dimensional: its subscripts change in two directions, and its access generally requires two subscripts.
- There is no two-dimensional array in the memory. The actual hardware memory of the two-dimensional array is continuously addressed, that is, there is only one-dimensional array in the memory, that is, after one row is put into the second row in sequence, which is the same as the storage method of the one-dimensional array.
#include <stdio.h> int main() { //Defines a two-dimensional array called a //It consists of three one-dimensional arrays. This one-dimensional array is int [4] //The array names of the three one-dimensional arrays are a[0],a[1],a[2] int a[3][4]; a[0][0] = 0; //...... a[2][3] = 12; //Assign a value to each element of the array int i = 0; int j = 0; int num = 0; for (i = 0; i < 3; i++) { for (j = 0; j < 4; j++) { a[i][j] = num++; } } //Traverse the array and output the value of each member for (i = 0; i < 3; i++) { for (j = 0; j < 4; j++) { printf("%d, ", a[i][j]); } printf("\n"); } return 0; }
5.3. 2 initialization of two-dimensional array
//Piecewise assignment int a[3][4] = {{ 1, 2, 3, 4 },{ 5, 6, 7, 8, },{ 9, 10, 11, 12 }}; int a[3][4] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8, }, { 9, 10, 11, 12 } }; //continuous assignment int a[3][4] = { 1, 2, 3, 4 , 5, 6, 7, 8, 9, 10, 11, 12 }; //You can only assign initial values to some elements. If not initialized, it is 0 int a[3][4] = { 1, 2, 3, 4 }; //All members are set to 0 int a[3][4] = {0}; //The number of elements is not defined in [] and must be initialized when defining int a[][4] = { 1, 2, 3, 4, 5, 6, 7, 8};
5.3. 3 array name
The array name is an address constant that represents the address of the first element in the array.
#include <stdio.h> int main() { //Defines a two-dimensional array called a //Is a two-dimensional array essentially a one-dimensional array with three elements //Each element is a one-dimensional array int[4] int a[3][4] = { 1, 2, 3, 4 , 5, 6, 7, 8, 9, 10, 11, 12 }; //The array name is the address of the first element of the array, and the 0th element of the two-dimensional array is a one-dimensional array //The array name of the 0th one-dimensional array is a[0] printf("a = %p\n", a); printf("a[0] = %p\n", a[0]); //Measure the memory space occupied by two-dimensional arrays. There are three one-dimensional arrays, and the space of each one-dimensional array is 4 * 4 //sizeof(a) = 3 * 4 * 4 = 48 printf("sizeof(a) = %d\n", sizeof(a)); //Measure the memory space occupied by the 0th element. a[0] is the array name of the 0th one-dimensional array int[4], 4 * 4 = 16 printf("sizeof(a[0]) = %d\n", sizeof(a[0]) ); //Measure the memory space occupied by the element in row 0 and column 0. The element in row 0 and column 0 is an int type, 4 bytes printf("sizeof(a[0][0]) = %d\n", sizeof(a[0][0])); //Find the number of rows of two-dimensional array printf("i = %d\n", sizeof(a) / sizeof(a[0])); // Find the number of two-dimensional array columns printf("j = %d\n", sizeof(a[0]) / sizeof(a[0][0])); //Find the total number of rows * columns of two-dimensional array printf("n = %d\n", sizeof(a) / sizeof(a[0][0])); return 0; }
5.3. 4 intensive training
#include <stdio.h> int main() { //Two dimensional array: five rows and three columns //Representative of the bank: from the eldest to the fifth //Columns represent subjects: language, number and foreign language float a[5][3] = { { 80, 75, 56 }, { 59, 65, 71 }, { 59, 63, 70 }, { 85, 45, 90 }, { 76, 77, 45 } }; int i, j, person_low[3] = { 0 }; float s = 0, lesson_aver[3] = { 0 }; for (i = 0; i < 3; i++) { for (j = 0; j < 5; j++) { s = s + a[j][i]; if (a[j][i] < 60) { person_low[i]++; } } lesson_aver[i] = s / 5; s = 0; } printf("Average score of each subject:\n"); for (i = 0; i < 3; i++) { printf("%.2f\n", lesson_aver[i]); } printf("Number of failed subjects:\n"); for (i = 0; i < 3; i++) { printf("%d\n", person_low[i]); } return 0; }
5.4 multidimensional array (understand)
The definition of multidimensional array is similar to that of 2D array. Its syntax format is as follows:
Array type modifier array name [n1][n2]... [nn];
int a[3][4][5];
A three-dimensional array is defined. The name of the array is a and the length of the array is 3. The elements of each array are a two-dimensional array. The length of the two-dimensional array is 4, and each element in the two-dimensional array is a one-dimensional array. The length of the one-dimensional array is 5 and the element type is int.
#include <stdio.h> int main() { //int a[3][4][5] ;// Defines a three-dimensional array with three two-dimensional arrays int[4][5] int a[3][4][5] = { { { 1, 2, 3, 4, 5 }, { 6, 7, 8, 9, 10 }, { 0 }, { 0 } }, { { 0 }, { 0 }, { 0 }, { 0 } }, { { 0 }, { 0 }, { 0 }, { 0 } } }; int i, j, k; for (i = 0; i < 3; i++) { for (j = 0; j < 4; j++) { for (k = 0; k < 5; k++) { //Add access element code printf("%d, ", a[i][j][k]); } printf("\n"); } } return 0; }
5.5 character arrays and strings
5.5. 1. Difference between character array and string
- There is no string data type in C language, which can be replaced by char array;
- The string must be an array of char, but the array of char may not be a string;
- The char array ending with the number 0 (equivalent to the character '\ 0') is a string, but if the char array does not end with the number 0, it is not a string, but an ordinary character array, so the string is a special char array.
#include <stdio.h> int main() { char c1[] = { 'c', ' ', 'p', 'r', 'o', 'g' }; //Normal character array printf("c1 = %s\n", c1); //Garbled because there is no '\ 0' terminator //The character array ending with '\ 0' ('\ 0' is the number 0) is a string char c2[] = { 'c', ' ', 'p', 'r', 'o', 'g', '\0'}; printf("c2 = %s\n", c2); //String processing takes' \ 0 '(number 0) as the terminator, and the following' H ',' l ',' l ',' e ',' o 'will not be output char c3[] = { 'c', ' ', 'p', 'r', 'o', 'g', '\0', 'h', 'l', 'l', 'e', 'o', '\0'}; printf("c3 = %s\n", c3); return 0; }
5.5. 2 initialization of string
#include <stdio.h> // C language has no string type, which is simulated by character array // C language string, with character '\ 0' and number 0 int main() { //No length specified, no 0 terminator, as many elements as there are char buf[] = { 'a', 'b', 'c' }; printf("buf = %s\n", buf); //Garbled code //The specified length, followed by elements without assignment, will be automatically supplemented with 0 char buf2[100] = { 'a', 'b', 'c' }; char buf[1000]={"hello"}; printf("buf2 = %s\n", buf2); //All elements are assigned a value of 0 char buf3[100] = { 0 }; //char buf4[2] = { '1', '2', '3' };// Array out of bounds char buf5[50] = { '1', 'a', 'b', '0', '7' }; printf("buf5 = %s\n", buf5); char buf6[50] = { '1', 'a', 'b', 0, '7' }; printf("buf6 = %s\n", buf6); char buf7[50] = { '1', 'a', 'b', '\0', '7' }; printf("buf7 = %s\n", buf7); //Using string initialization, the compiler will automatically fill in 0 after it, which is commonly used char buf8[] = "agjdslgjlsdjg"; //It's best not to connect numbers after '\ 0'. It's possible that several numbers are just an escape character //'\ ddd' octal literal character, '\ xdd' hexadecimal transfer character // \012 is equivalent to \ n char str[] = "\012abc"; printf("str == %s\n", str); return 0; }
5.5. 3 input and output of string
Because the string adopts the '\ 0' flag, the input and output of the string will become simple and convenient.
#include <stdio.h> int main() { char str[100]; printf("input string1 : \n"); scanf("%s", str);//scanf('% s', str) is separated by spaces by default printf("output:%s\n", str); return 0; }
- gets()
#include <stdio.h> char *gets(char *s); Function: read characters from standard input and save them to s The specified memory space until a newline occurs or the end of the file is read. Parameters: s: First address of string Return value: Success: read in string Failed: NULL
Differences between gets(str) and scanf('% s', str):
1. gets(str) allows the input string to contain spaces
2. scanf('% s', str) cannot contain spaces
Note: because scanf() and gets() cannot know the size of string s, they must encounter a newline character or receive input until the end of the file. Therefore, it is easy to cause the character array to cross the boundary (buffer overflow).
char str[100]; printf("Please enter str: "); gets(str); printf("str = %s\n", str);
- fgets()
#include <stdio.h> char *fgets(char *s, int size, FILE *stream); Function: from stream Read in characters from the specified file and save to s The specified amount of memory space until a newline character appears, the end of the file is read, or has been read size - 1 Characters are added automatically at the end '\0' Ends as a string. Parameters: s: character string size: Specifies the length of the maximum read string( size - 1) stream: File pointer. If you read the string entered by the keyboard, write it as stdin Return value: Success: String successfully read End of file read or error: NULL
When fgets() reads a string entered by the user through the keyboard, it also takes the carriage return entered by the user as a part of the string. When inputting a string through scanf and gets, it does not contain the ending "\ n", but it ends with "\ n" through fgets. The fgets() function is safe and there is no buffer overflow problem.
char str[100]; printf("Please enter str: "); fgets(str, sizeof(str), stdin); printf("str = \"%s\"\n", str);
- puts()
#include <stdio.h> int puts(const char *s); Function: standard equipment output s String, which is automatically output after the output is completed'\n'. Parameters: s: First address of string Return value: Success: non negative Failed:-1 #include <stdio.h> int main() { printf("hello world"); puts("hello world"); return 0; }
- fputs()
#include <stdio.h> int fputs(const char * str, FILE * stream); Function: will str Writes the specified string to stream String terminator in the specified file '\0' Do not write to file. Parameters: str: character string stream: File pointer. If the string is output to the screen, it is fixed as stdout Return value: Success: 0 Failed:-1
Fputs() is the file operation version of puts(), but fputs() will not automatically output a '\ n'.
printf("hello world"); puts("hello world"); fputs("hello world", stdout);
- strlen()
#include <string.h> size_t strlen(const char *s); Function: calculate specified string s The length of the string, excluding the string terminator'\0' Parameters: s: First address of string Return value: String s The length of the, size_t by unsigned int type char str[] = "abc\0defg"; int n = strlen(str); printf("n = %d\n", n);
5.5. 4 intensive training: String append
#include <stdio.h> int main() { char str1[] = "abcdef"; char str2[] = "123456"; char dst[100]; int i = 0; while (str1[i] != 0) { dst[i] = str1[i]; i++; } int j = 0; while (str2[j] != 0) { dst[i + j] = str2[j]; j++; } dst[i + j] = 0; //String Terminator printf("dst = %s\n", dst); return 0; }
6. Function
6.1 general
6.1. 1 function classification
C program is composed of functions. The code we write is executed from the main function main(). Function is the basic module of C program and the program code unit used to complete specific tasks.
From the perspective of function definition, functions can be divided into system functions and user-defined functions:
- System functions, i.e. library functions: these functions are provided by the compilation system. Users do not need to define these functions themselves, but can directly use them, such as our common print function printf().
- User defined function: used to solve the special needs of users.
6.1. 2 function
- The use of function can save the writing of repeated code and reduce the code repetition rate
// Find the maximum of two numbers int max(int a, int b) { if (a > b){ return a; } else{ return b; } } int main() { // Operation 1 // ...... int a1 = 10, b1 = 20, c1 = 0; c1 = max(a1, b1); // Call max() // Operation 2 // ...... int a2 = 11, b2 = 21, c2 = 0; c2 = max(a2, b2); // Call max() // ...... return 0; }
- Function can make the program more modular, which is conducive to the reading, modification and improvement of the program
Suppose we write a program to realize the following functions: read in a line of numbers; Sort numbers; Find their average; Print out a histogram. If we write these operations directly in main(), the user may feel that the code will be a little messy. However, if we use functions, we can make the program clearer and modular:
#include <stdio.h> int main() { float list[50]; // This is just an example. The function has not been implemented yet readlist(list, 50); sort(list, 50); average(list, 50); bargraph(list, 50); return 0; }
Here we can understand that programs are like companies. Companies are composed of departments, which are similar to the functions of C programs. By default, the company is a large department (in the case of only one department), which is equivalent to the main () function of C program. If the company is relatively small (the program is relatively small) and the tasks are few and simple, one department can be competent (main() function). However, if the company is large (large-scale applications) and has many and complex tasks, if it is only managed by a department (equivalent to no department and no division of labor), we can imagine how chaotic the management and operation of the company will be. It is not that it can not operate, it is just that it is imperfect, If it is divided into departments according to the company's requirements (encapsulating a function according to the function), the recruitment is in the charge of the administrative department, and the R & D is in the charge of the technical department, so that the division of labor is clear, the structure is clear, it is convenient for management, and all departments can coordinate with each other.
6.1. 3 function call: generate random number
When calling a function, you need to care about 5 elements:
- Header file: contains the specified header file
- Function name: the function name must be the same as the name declared in the header file
- Function: you need to know what this function can do before calling
- Parameter: parameter type to match
- Return value: receive the return value as required
#include <time.h> time_t time(time_t *t); Function: get the current system time Parameter: often set to NULL Return value: current system time, time_t amount to long Type in milliseconds
#include <stdlib.h> void srand(unsigned int seed); Function: used to set rand()Random seed when generating random number Parameter: if every time seed equal, rand()Generate random number equality Return value: None
#include <stdlib.h> int rand(void); Function: return a random value Parameter: None Return value: random number
#include <stdio.h> #include <time.h> #include <stdlib.h> int main() { time_t tm = time(NULL);//Get system time srand((unsigned int)tm);//Random seeds only need to be set once int r = rand(); printf("r = %d\n", r); return 0; }
6.2 definition of function
6.2. 1 function definition format
General form of function definition:
Return type function name (formal parameter list)
{
Data definition part;
Execute the statement part;
}
6.2. 2 function name, formal parameter, function body and return value
-
Function name
In theory, you can choose a name at will. The best name is known by the name. Users should know the function when they see the function name. Note that there is a circle sign () after the function name, which means that it is a function, not an ordinary variable name. -
parameter list
The formal parameters specified when defining a function do not occupy the storage unit in memory when there is no function call. Therefore, they are called formal parameters or virtual parameters, abbreviated as formal parameters, which means that they are not actual data. Therefore, the variables in the formal parameters cannot be assigned.
void max(int a = 10, int b = 20) // error, the formal parameter cannot be assigned { }
The formal parameter specified when defining a function must be in the form of type + variable:
//1: right, type + variable void max(int a, int b) { } //2: error, only type, no variable void max(int, int) { } //3: error, only variables, no types int a, int b; void max(a, b) { }
The formal parameters specified when defining a function can be optional. They are designed according to the needs of the function. If there are no formal parameters, the parentheses are empty, or write a void keyword:
//No formal parameters, parentheses are empty
void max() { }
//There is no formal parameter, and the parenthesis content is void keyword
void max(void) { }
-
Function body
The content in curly braces {} is the content of the function body. Here is the process of function implementation, which is not very different from the previous code writing. We used to write the code in the main() function, but now we just write these in other functions. -
Return value
The return value of the function is obtained through the return statement in the function. The value after return can also be an expression.
- Try to ensure that the value of the expression in the return statement and the return type of the function are of the same type.
int max() // The return value of the function is of type int { int a = 10; return a;// The return value a is of type int, and the return type of the function is also of type int }
- If the return type of the function is inconsistent with the value of the expression in the return statement, the return type of the function shall prevail, that is, the return type of the function determines the type of the return value. For numeric data, type conversion can be performed automatically.
double max() // The return value of the function is of type double { int a = 10; return a;// The return value a is of type int, which will be converted to type double and then returned }
Note: if the type returned by the function is inconsistent with the value of the expression in the return statement, and it cannot automatically perform type conversion, the program will report an error.
- Another function of the return statement is to interrupt the execution function of the return, which is similar to the break interrupt loop and switch statements.
int max() { return 1;// After execution, the function has been interrupted, so the following return 2 cannot be executed return 2;// Not implemented }
4. If the function has a return value, return must be followed by a value. If the function has no return value, a void keyword must be written in front of the function name. At this time, we can also interrupt the function through return (or not). However, at this time, return does not have content (semicolon ") Except).
void max()// It is better to have void keyword { return; // Interrupt function, this is optional }
6.3 function call
After defining the function, we need to call this function to execute the code segment in this function. This is different from the main() function. main() sets the main function to be called automatically for the compiler without human calls. We all call other functions in the main() function. There is only one main() function in a C program.
6.3. 1 function execution process
#include <stdio.h> void print_test() { printf("this is for test\n"); } int main() { print_test(); // print_ Call of test function return 0; }
- Enter the main() function
- Call print_test() function:
a. It will look for a function definition called "print_test" before the main() function;
b. If found, then check the parameters of the function. There are no parameters passed when calling the function, and there are no formal parameters in the function definition. The parameter types match;
c. Start print_test() function. At this time, the execution in the main() function will block (stop)
)In print_test() and wait for print_ Execution of the test() function.
3.print_ After the test() function is executed (print a sentence here), main() will continue to execute until return 0, and the program is completed.
6.3. 2 formal and actual parameters of function
- Formal parameters appear in the function definition and can be used in the whole function body. They cannot be used without the function.
- The argument appears in the calling function. After entering the called function, the argument cannot be used.
- The data transfer of argument variables to formal parameter variables is "value transfer", that is, one-way transfer. Only arguments are passed to formal parameters, not formal parameters.
- When the function is called, the compiling system temporarily allocates storage units to formal parameters. After the call, the formal parameter unit is released.
- Argument unit and formal parameter unit are different units. After the call, the formal parameter unit is released. After the function call ends and returns to the calling function, the formal parameter variable can no longer be used
- The argument unit remains and maintains its original value. Therefore, when a called function is executed, if the value of the formal parameter changes, it will not change the value of the argument in the calling function.
6.3. 3 parameterless function call
If you call a parameterless function, you cannot add "arguments", but parentheses cannot be omitted.
// Definition of function void test() { } int main() { // Function call test(); // right, parentheses () cannot be omitted test(250); // error, the function is defined without parameters return 0; }
3 6.3. 4 parametric function call
a) If the argument table column contains multiple arguments, the parameters are separated by commas.
// Definition of function void test(int a, int b) { } int main() { int p = 10, q = 20; test(p, q); // Function call return 0; }
b) The number of arguments and formal parameters should be equal, and the types should match (the same or assignment compatible). Arguments and formal parameters correspond in order, and data is passed one-to-one.
c) Arguments can be constants, variables or expressions. No matter what type of quantity the arguments are, they must have definite values when making a function call in order to pass these values to the formal parameters. Therefore, the variables here are defined and assigned values outside the parentheses ().
// Definition of function void test(int a, int b) { } int main() { // Function call int p = 10, q = 20; test(p, q); // right test(11, 30 - 10); // right test(int a, int b); // error, variables should not be defined in parentheses return 0; }
6.3. 5 function return value
a) If the function definition has no return value, the void keyword cannot be written when calling the function, and the return value of the function cannot be received when calling the function.
// Definition of function void test() { } int main() { // Function call test(); // right void test(); // Error, the void keyword can only appear in the definition, not in the calling place int a = test(); // error, the function definition has no return value at all return 0; }
b) If the function defines a return value, the return value can be used according to the user's needs. However, if we need to use the return value of the function, we need to define a variable of matching type to receive it.
// Function. The return value is of type int int test() { } int main() { // Function call int a = test(); // right, a is of type int int b; b = test(); // right, and above char *p = test(); // Although the successful call is meaningless, p is char *, the return value of the function is int, and the type does not match // error, you must define a variable of matching type to receive the return value // int is just a type and does not define a variable int = test(); // error, you must define a variable of matching type to receive the return value // int is just a type and does not define a variable int test(); return 0; }
6.4 function declaration
If a user-defined function is used, and the function is not in the same file as the function calling it (i.e. the calling function), or the position of the function definition is after the calling function, the called function must be declared before calling this function.
The so-called function declaration is to inform the compilation system of the relevant information of the function in advance when the function is not defined, which is equivalent to telling the compiler that the function is defined later, so that the compilation can proceed normally.
Note: a function can only be defined once, but can be declared multiple times.
#include <stdio.h> int max(int x, int y); // The semicolon cannot be omitted in the declaration of a function // int max(int, int); // Another way int main() { int a = 10, b = 25, num_max = 0; num_max = max(a, b); // Function call printf("num_max = %d\n", num_max); return 0; } // Definition of function int max(int x, int y) { return x > y ? x : y; }
Difference between function definition and declaration:
- Definition refers to the establishment of function functions, including specifying function name, function type, formal parameters and their types, function body, etc. it is a complete and independent function unit.
- The function of the declaration is to inform the compiling system of the name, type and number, type and order of the function, function type and formal parameters (note that the function body is not included), so that when compiling the statement containing the function call, it can be checked accordingly (for example, whether the function name is correct, and whether the type and number of arguments and formal parameters are consistent).
6.5 main function and exit function
The result of calling exit and return in the main function is the same, but calling return in the subfunction only terminates the subfunction, and calls exit in the subfunction, so the program terminates.
#include <stdio.h> #include <stdlib.h> void fun() { printf("fun\n"); //return; exit(0); } int main() { fun(); while (1); return 0; }
6.6 multi file (sub file) programming
6.6. 1 sub file programming
- Put the function declaration in the header file XXX H, the corresponding header file is included in the main function
- In the header file corresponding to XXX Realize XXX in C H declared function
6.6. 2. Prevent repeated inclusion of header files
When a project is large, it is often divided into files. At this time, you may accidentally include the same header file multiple times, or the header file may be nested and included.
a.h includes b.h:
#include "b.h"
b.h includes a.h:
#include "a.h"
main. Header file used in C:
#include "a.h"
int main() { return 0; }
When compiling the above example, the following errors will occur:
In order to avoid the same file being include d multiple times, there are two methods in C/C + +, one is #ifndef method, the other is #pragma once method.
Method 1:
#ifndef __SOMEFILE_H__ #define __SOMEFILE_H__ // Declaration statement #endif
Method 2:
#pragma once // Declaration statement
7. Pointer
7.1 general
7.1. 1 memory
Memory meaning:
- Memory: in the composition of a computer, it is used to store programs and data and assist the CPU in operation and processing.
- Memory: internal memory, temporary program / data - SRAM, DRAM, DDR, DDR2 and DDR3 are lost after power failure.
- External memory: external memory, which can store programs / data for a long time - ROM, ERRROM, FLASH (NAND, NOR), hard disk and optical disc will not be lost when power is off.
Memory is the bridge between CPU and hard disk:
- Temporarily store the operation data in the CPU
- Temporarily store data exchanged with external memory such as hard disk
7.1. 2 physical memory and storage address space
Two concepts about memory: physical memory and storage address space.
Physical memory: a specific memory chip that actually exists.
- Memory module inserted on motherboard
- Display RAM chip on display card
- RAM chip and ROM chip on various adapter cards
Storage address space: the range of memory encoding. We often say memory in software refers to this layer of meaning.
- Encoding: assign a number to each physical storage unit (one byte)
- Addressing: the corresponding storage unit can be found according to the assigned number to complete data reading and writing
7.1. 3 memory address
- Abstract the memory into a large one-dimensional character array.
- Encoding is to assign a 32-bit or 64 bit number to each byte of memory (related to 32-bit or 64 bit processors).
- This memory number is called the memory address.
Each data in the memory will be assigned a corresponding address:
- char: allocate an address per byte
- int: allocate four addresses for four bytes
- float, struct, function, array, etc
7.1. 4 pointer and pointer variable
- Each byte of the memory area has a number, which is "address".
- If a variable is defined in the program, when the program is compiled or run, the system will allocate memory units to the variable and determine its memory address (number)
- The essence of pointer is memory "address". The pointer is the address, and the address is the pointer.
- The pointer is the number of the memory unit, and the pointer variable is the variable that stores the address.
- Usually when we describe, we will abbreviate pointer variables as pointers. In fact, they have different meanings.
7.2 basic knowledge of pointer
7.2. 1 Definition and use of pointer variables
- Pointer is also a data type, and pointer variable is also a variable
- The address of the person to whom the pointer variable points is assigned to the pointer variable
- The "*" operator operates on the memory space pointed to by the pointer variable
#include <stdio.h> int main() { int a = 0; char b = 100; printf("%p, %p\n", &a, &b); //Print the address of a and B //Int * represents a data type, int * pointer type, and p is the variable name //Defines a pointer type variable that can point to the address of an int type variable int *p; p = &a;//Assign the address of a to the variable p, which is also a variable, and the value is a memory address number printf("%d\n", *p);//p points to the address of a, * p is the value of A char *p1 = &b; printf("%c\n", *p1);//*p1 points to the address of b, * p1 is the value of b return 0; }
Note: & you can get the address of a variable in memory. However, the register variable cannot be retrieved, because the register variable is not in memory, but in the CPU, so there is no address.
7.2. 2 modify the value of the variable indirectly through the pointer
int a = 0; int b = 11; int *p = &a; *p = 100; printf("a = %d, *p = %d\n", a, *p); p = &b; *p = 22; printf("b = %d, *p = %d\n", b, *p);
7.2. 3 pointer size
- Use sizeof() to measure the size of the pointer and always get: 4 or 8
- sizeof() measures the size of the pointer variable pointing to the storage address
- On 32-bit platforms, all pointers (addresses) are 32 bits (4 bytes)
- On 64 bit platforms, all pointers (addresses) are 64 bits (8 bytes)
int *p1; int **p2; char *p3; char **p4; printf("sizeof(p1) = %d\n", sizeof(p1)); printf("sizeof(p2) = %d\n", sizeof(p2)); printf("sizeof(p3) = %d\n", sizeof(p3)); printf("sizeof(p4) = %d\n", sizeof(p4)); printf("sizeof(double *) = %d\n", sizeof(double *));
7.2. 4 field pointer and null pointer
The pointer variable is also a variable. If it is a variable, it can be assigned arbitrarily without crossing the boundary (4 bytes for 32 bits and 8 bytes for 64 bits). However, it is meaningless to assign any value to the pointer variable, because such a pointer becomes a wild pointer, and the area pointed to by the pointer is unknown (the operating system does not allow the operation of the memory area pointed to by the pointer). Therefore, the wild pointer will not directly cause an error, and the operation of the memory area pointed to by the wild pointer will cause a problem.
int a = 100; int *p; p = a; //Assign the value of a to the pointer variable p, P is the wild pointer, ok, there will be no problem, but it doesn't make sense p = 0x12345678; //Assign a value to the pointer variable p, P is the wild pointer, ok, there will be no problem, but it doesn't make sense *p = 1000; //Operation field pointer points to unknown area, memory problem, err
*However, both wild pointer and valid pointer variables store values. In order to mark that this pointer variable does not point to any variable (idle and available), NULL can be assigned to this pointer in C language, so as to mark that this pointer is a NULL pointer without any pointer.
int p = NULL;
NULL Is a macro constant with a value of 0: #define NULL ((void *)0)
7.2. 5 universal pointer void*
void *The pointer can point to the memory space of any variable: void *p = NULL; int a = 10; p = (void *)&a; //When pointing to a variable, it is best to convert it to void* //When using the memory pointed to by the pointer variable, it is converted to int* *( (int *)p ) = 11; printf("a = %d\n", a);
7.2. 6 pointer variable modified by const
int a = 100; int b = 200; //pointer to const //Modified *, pointer pointing to memory area cannot be modified, and pointer pointing can be changed const int * p1 = &a; //Equivalent to int const * P1 = & A; //*p1 = 111; //err p1 = &b; //ok //constant pointer //Modify p1, the pointer cannot be changed, and the memory pointed to by the pointer can be modified int * const p2 = &a; //p2 = &b; //err *p2 = 222; //ok
When editing the program, the pointer is used as a function parameter. If you do not want to modify the value of the memory space corresponding to the pointer, you need to use const to modify the pointer data type.
7.3 pointers and arrays
7.3. 1 array name
The array name is the address of the first element of the array, but it is a constant:
int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
printf("a = %p\n", a);
printf("&a[0] = %p\n", &a[0]);
//a = 10; //err, the array name is just a constant and cannot be modified
7.3. 2 pointer operation array element
#include <stdio.h> int main() { int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int i = 0; int n = sizeof(a) / sizeof(a[0]); for (i = 0; i < n; i++) { //printf("%d, ", a[i]); printf("%d, ", *(a+i)); } printf("\n"); int *p = a; //Defines the address where a pointer variable holds a for (i = 0; i < n; i++) { p[i] = 2 * i; } for (i = 0; i < n; i++) { printf("%d, ", *(p + i)); } printf("\n"); return 0; }
7.3. 3 pointer addition and subtraction
1) Addition operation
- Pointer calculation is not a simple addition of integers
- If it is an int *, + 1 will increase the size of an int
- If it is a char *, + 1 results in an increase in char size
#include <stdio.h> int main() { int a; int *p = &a; printf("%d\n", p); p += 2;//Moved 2 int s printf("%d\n", p); char b = 0; char *p1 = &b; printf("%d\n", p1); p1 += 2;//Moved 2 char s printf("%d\n", p1); return 0; }
Manipulate array elements by changing the pointer:
#include <stdio.h> int main() { int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int i = 0; int n = sizeof(a) / sizeof(a[0]); int *p = a; for (i = 0; i < n; i++) { printf("%d, ", *p); p++; } printf("\n"); return 0; }
2) Subtraction operation
Example 1: #include <stdio.h> int main() { int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int i = 0; int n = sizeof(a) / sizeof(a[0]); int *p = a+n-1; for (i = 0; i < n; i++) { printf("%d, ", *p); p--; } printf("\n"); return 0; } Example 2: #include <stdio.h> int main() { int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int *p2 = &a[2]; //Address of the second element int *p1 = &a[1]; //Address of the first element printf("p1 = %p, p2 = %p\n", p1, p2); int n1 = p2 - p1; //n1 = 1 int n2 = (int)p2 - (int)p1; //n2 = 4 printf("n1 = %d, n2 = %d\n", n1, n2); return 0; }
7.3. 4 pointer array
Pointer array, which is an array. Each element of the array is a pointer type.
#include <stdio.h> int main() { //Pointer array int *p[3]; int a = 1; int b = 2; int c = 3; int i = 0; p[0] = &a; p[1] = &b; p[2] = &c; for (i = 0; i < sizeof(p) / sizeof(p[0]); i++ ) { printf("%d, ", *(p[i])); } printf("\n"); return 0; }
7.4 multi level pointer
- C language allows the existence of multi-level pointers. In the actual program, the first level pointer is the most commonly used, followed by the second level pointer.
- A secondary pointer is a pointer to the address of a primary pointer variable.
- Level 3 pointer is basically unnecessary, but it will be tested in the exam.
int a = 10; int *p = &a; //Primary pointer *p = 100; //*p is a int **q = &p; //*q is p //**q is a int ***t = &q; //*t is q //**t is p //***t is a
7.5 pointers and functions
7.5. 1 function parameters change the value of arguments
#include <stdio.h> void swap1(int x, int y) { int tmp; tmp = x; x = y; y = tmp; printf("x = %d, y = %d\n", x, y); } void swap2(int *x, int *y) { int tmp; tmp = *x; *x = *y; *y = tmp; } int main() { int a = 3; int b = 5; swap1(a, b); //pass by value printf("a = %d, b = %d\n", a, b); a = 3; b = 5; swap2(&a, &b); //Address delivery printf("a2 = %d, b2 = %d\n", a, b); return 0; }
7.6. 2 array name as function parameter
When the array name is used as a function parameter, the formal parameter of the function will degenerate into a pointer:
#include <stdio.h> void printArrary(int *a, int n) { int i = 0; for (i = 0; i < n; i++) { printf("%d, ", a[i]); } printf("\n"); } int main() { int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int n = sizeof(a) / sizeof(a[0]); //Array name as function parameter printArrary(a, n); return 0; }
7.6. 3 the pointer is used as the return value of the function
#include <stdio.h> int a = 10; int *getA() { return &a; } int main() { *( getA() ) = 111; printf("a = %d\n", a); return 0; }
7.7 pointers and strings
7.7. 1 character pointer
#include <stdio.h> int main() { char str[] = "hello world"; char *p = str; *p = 'm'; p++; *p = 'i'; printf("%s\n", str); p = "mike jiang"; printf("%s\n", p); char *q = "test"; printf("%s\n", q); return 0; }
7.7. 2 character pointer as function parameter
#include <stdio.h> void mystrcat(char *dest, const char *src) { int len1 = 0; int len2 = 0; while (dest[len1]) { len1++; } while (src[len2]) { len2++; } int i; for (i = 0; i < len2; i++) { dest[len1 + i] = src[i]; } } int main() { char dst[100] = "hello mike"; char src[] = "123456"; mystrcat(dst, src); printf("dst = %s\n", dst); return 0; }
7.7. 3 pointer variable modified by const
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { //const modifies a variable to be read-only const int a = 10; //a = 100; //err //Pointer variable, memory pointed to by pointer, 2 different concepts char buf[] = "aklgjdlsgjlkds"; //From left to right, skip the type to see which character is decorated //If it is *, the memory pointed to by the pointer cannot be changed //If it is a pointer variable, it means that the pointer cannot be changed and the pointer value cannot be modified const char *p = buf; // Equivalent to char const *p1 = buf above; //p[1] = '2'; //err p = "agdlsjaglkdsajgl"; //ok char * const p2 = buf; p2[1] = '3'; //p2 = "salkjgldsjaglk"; //err //p3 is read-only, the pointing cannot be changed, and the pointing memory cannot be changed const char * const p3 = buf; return 0; }
7.7. 4. The pointer array is used as the formal parameter of the main function
int main(int argc, char *argv[]);
- The main function is called by the operating system. The first parameter indicates the number of members of the argc array. Each member of the argv array is of type char *
- argv is a string array of command line arguments
- argc represents the number of command line parameters, and the program name itself is a parameter
#include <stdio.h> //argc: number of parameters passed (including executable programs) //argv: pointer array, pointing to the input parameter int main(int argc, char *argv[]) { //Pointer array, which is an array, and each element is a pointer char *a[] = { "aaaaaaa", "bbbbbbbbbb", "ccccccc" }; int i = 0; printf("argc = %d\n", argc); for (i = 0; i < argc; i++) { printf("%s\n", argv[i]); } return 0; }
7.7. 5 common string application models for project development
- While and do while models in str
Use the strstr standard library function to find out the number of substr s in a string.
a)while model
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { char *p = "11abcd111122abcd333abcd3322abcd3333322qqq"; int n = 0; while ((p = strstr(p, "abcd")) != NULL) { //If you can come in, there must be a matching substring //Reset start position p = p + strlen("abcd"); n++; if (*p == 0) //If to the terminator { break; } } printf("n = %d\n", n); return 0; }
b) Do while model
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { char *p = "11abcd111122abcd333abcd3322abcd3333322qqq"; int n = 0; do { p = strstr(p, "abcd"); if (p != NULL) { n++; //Cumulative number //Reset the start point of the lookup p = p + strlen("abcd"); } else //If there is no matching string, jump out of the loop { break; } } while (*p != 0); //If not to the end printf("n = %d\n", n); return 0; }
- Two plug model
Find the number of non empty string elements:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> int fun(char *p, int *n) { if (p == NULL || n == NULL) { return -1; } int begin = 0; int end = strlen(p) - 1; //Start on the left //If the current character is empty and does not end while (p[begin] == ' ' && p[begin] != 0) { begin++; //The position moves one bit from the right } //Move from right to left while (p[end] == ' ' && end > 0) { end--; //Move left } if (end == 0) { return -2; } //Number of non empty elements *n = end - begin + 1; return 0; } int main(void) { char *p = " abcddsgadsgefg "; int ret = 0; int n = 0; ret = fun(p, &n); if (ret != 0) { return ret; } printf("Number of non empty string elements:%d\n", n); return 0; }
- String inversion model (inverse)
#include <stdio.h> #include <stdlib.h> #include <string.h> int inverse(char *p) { if (p == NULL) { return -1; } char *str = p; int begin = 0; int end = strlen(str) - 1; char tmp; while (begin < end) { //Exchange element tmp = str[begin]; str[begin] = str[end]; str[end] = tmp; begin++; //Move position right end--; //Move left position } return 0; } int main(void) { //char *str = "abcdefg"; // File constant area, content cannot be modified char str[] = "abcdef"; int ret = inverse(str); if (ret != 0) { return ret; } printf("str ========== %s\n", str); return 0; }
7.7. 8 string processing function
- strcpy()
#include <string.h> char *strcpy(char *dest, const char *src); Function: handle src Copy the string pointed to to to dest In the space pointed to,'\0'It will also be copied Parameters: dest: Destination string first address src: Source character prefix address Return value: Success: Return dest The first address of the string Failed: NULL
Note: if the memory space referred to by the parameter dest is not large enough, it may cause a buffer overflow error.
char dest[20] = "123456789"; char src[] = "hello world"; strcpy(dest, src); printf("%s\n", dest);
- strncpy()
#include <string.h> char *strncpy(char *dest, const char *src, size_t n); Function: handle src Points to the front of the string n Characters copied to dest In the space pointed to, whether to copy the terminator depends on whether the specified length contains'\0'. Parameters: dest: Destination string first address src: Source character prefix address n: Specify the number of strings to copy Return value: Success: Return dest The first address of the string Failed: NULL char dest[20] ; char src[] = "hello world"; strncpy(dest, src, 5); printf("%s\n", dest); dest[5] = '\0'; printf("%s\n", dest);
- strcat()
#include <string.h> char *strcat(char *dest, const char *src); Function: will src Connect string to dest The tail of the,'\0'Will also add the past Parameters: dest: Destination string first address src: Source character prefix address Return value: Success: Return dest The first address of the string Failed: NULL char str[20] = "123"; char *src = "hello world"; printf("%s\n", strcat(str, src));
4) strncat() #include <string.h> char *strncat(char *dest, const char *src, size_t n); Function: will src Before string n Characters connected to dest The tail of the,'\0'Will also add the past Parameters: dest: Destination string first address src: Source character prefix address n: Specifies the number of strings to append Return value: Success: Return dest The first address of the string Failed: NULL char str[20] = "123"; char *src = "hello world"; printf("%s\n", strncat(str, src, 5));
5) strcmp() #include <string.h> int strcmp(const char *s1, const char *s2); Function: comparison s1 and s2 The size of is compared with characters ASCII Code size. Parameters: s1: First address of string 1 s2: First address of string 2 Return value: Equal: 0 Greater than:>0 On different operating systems strcmp The results will be returned differently ASCII Difference Less than:<0 char *str1 = "hello world"; char *str2 = "hello mike"; if (strcmp(str1, str2) == 0) { printf("str1==str2\n"); } else if (strcmp(str1, str2) > 0) { printf("str1>str2\n"); } else { printf("str1<str2\n"); }
- strncmp()
#include <string.h> int strncmp(const char *s1, const char *s2, size_t n); Function: comparison s1 and s2 front n The size of characters, compared with characters ASCII Code size. Parameters: s1: First address of string 1 s2: First address of string 2 n: Specifies the number of comparison strings Return value: Equal: 0 Greater than: > 0 Less than: < 0 char *str1 = "hello world"; char *str2 = "hello mike"; if (strncmp(str1, str2, 5) == 0) { printf("str1==str2\n"); } else if (strcmp(str1, "hello world") > 0) { printf("str1>str2\n"); } else { printf("str1<str2\n"); }
- sprintf()
#include <stdio.h> int sprintf(char *str, const char *format, ...); Function: according to parameters format String to convert and format the data, and then output the result to str In the specified space until the string terminator appears '\0' until. Parameters: str: First address of string format: String format, usage and printf()equally Return value: Success: number of characters actually formatted Failed: - 1 char dst[100] = { 0 }; int a = 10; char src[] = "hello world"; printf("a = %d, src = %s", a, src); printf("\n"); int len = sprintf(dst, "a = %d, src = %s", a, src); printf("dst = \" %s\"\n", dst); printf("len = %d\n", len);
- sscanf()
#include <stdio.h> int sscanf(const char *str, const char *format, ...); Function: from str Reads the data according to the specified string, and reads the data according to the parameters format String to convert and format data. Parameters: str: The first address of the specified string format: String format, usage and scanf()equally Return value: Success: number of parameters, number of successfully converted values Failed: - 1 char src[] = "a=10, b=20"; int a; int b; sscanf(src, "a=%d, b=%d", &a, &b); printf("a:%d, b:%d\n", a, b);
- strchr()
#include <string.h> char *strchr(const char *s, int c); Function: in string s Find letters in c Location of occurrence Parameters: s: First address of string c: Matching letters(character) Return value: Success: returns the first occurrence c address Failed: NULL char src[] = "ddda123abcd"; char *p = strchr(src, 'a'); printf("p = %s\n", p);
- strstr()
#include <string.h> char *strstr(const char *haystack, const char *needle); Function: in string haystack Find string in needle Location of occurrence Parameters: haystack: Source string first address needle: First address of matching string Return value: Success: returns the first occurrence needle address Failed: NULL char src[] = "ddddabcd123abcd333abcd"; char *p = strstr(src, "abcd"); printf("p = %s\n", p);
- strtok()
#include <string.h> char *strtok(char *str, const char *delim); Function: to split the string into fragments. When strtok()In parameter s Parameter found in string delim When the split character contained in the, The character is changed to\0 Character. When multiple characters appear in succession, only the first one is replaced with\0. Parameters: str: Point to the string to be split delim: Splits all characters contained in the string Return value: Success: the first address of the split string Failed: NULL
- On the first call: strtok() must give the parameter s string
- In subsequent calls, the parameter s is set to NULL, and each successful call returns a pointer to the segmented fragment
char a[100] = "adc*fvcv*ebcy*hghbdfg*casdert"; char *s = strtok(a, "*");//Take out the substring divided by "*" while (s != NULL) { printf("%s\n", s); s = strtok(NULL, "*"); }
- atoi()
#include <stdlib.h> int atoi(const char *nptr); Function: atoi()Can scan nptr String, skip the preceding space character, and do not start the conversion until it encounters a number or sign, but encounter a non number or string terminator('\0')To end the conversion and return the result to the return value. Parameters: nptr: String to be converted Return value: integer after successful conversion
Similar functions are:
- atof(): converts a decimal string to a floating-point number.
- atol(): converts a string to a long type
char str1[] = "-10"; int num1 = atoi(str1); printf("num1 = %d\n", num1); char str2[] = "0.123"; double num2 = atof(str2); printf("num2 = %lf\n", num2);
7.8 pointer summary
8. Memory management
8.1 scope
The scope of C language variables is divided into:
- Code block scope (code block is a piece of code between {})
- Function scope
- File scope
8.1. 1 local variable
Local variables are also called auto automatic variables (auto can be written or not). Generally, the variables defined inside the code block {} are automatic variables, which have the following characteristics:
- Defined within a function, valid only within the scope of the function
- Defined in a compound statement, valid only in a compound statement
- With the end of a function call or a compound statement, the declaration cycle of a local variable ends
- If no initial value is assigned, the content is random
#include <stdio.h> void test() { //It's the same whether auto writes or not //auto can only appear inside {} auto int b = 10; } int main(void) { //b = 100; //err, there is no B in the main scope if (1) { //Defined in a compound statement, valid only in a compound statement int a = 10; printf("a = %d\n", a); } //a = 10; //err leaves the compound statement of if(), and a no longer exists return 0; }
8.1. 2 static local variables
- The scope of the static local variable is also valid within the defined function
- The life cycle of static local variable is the same as that of the program. At the same time, the value of staitc local variable is initialized only once, but it can be assigned multiple times
- If the static local variable is not assigned an initial value, it will be automatically assigned by the system: the numerical variable will be automatically assigned an initial value of 0, and the character variable will be assigned an empty character
#include <stdio.h> void fun1() { int i = 0; i++; printf("i = %d\n", i); } void fun2() { //The static local variable has no assignment, the system assigns a value of 0, and it will only be initialized once static int a; a++; printf("a = %d\n", a); } int main(void) { fun1(); fun1(); fun2(); fun2(); return 0; }
8.1. 3 global variables
- It is defined outside the function and can be shared by functions in this document and other documents. If functions in other documents call this variable, it must be declared with extern
- The life cycle of a global variable is the same as that of a program
- Global variables of different files cannot have the same name
8.1. 4 static global variables
- Defined outside the function, the scope is limited to the defined file
- Static global variables of different files can have the same name, but the scope does not conflict
- The life cycle of static global variable is the same as that of the program, and the value of staitc global variable is initialized only once
8.1. 5 external global variable declaration
extern int a; Declare a variable. The global variable has been defined in other files. Here, it is only declared, not defined.
8.1. 6 global and static functions
In C language, functions are global by default. Using the keyword static can declare a function static. Defining a function as static means that the function can only be used in the file that defines the function and cannot be called in other files. Even if the function is declared in other files, it is useless.
The name of the staitc function in different files can be the same.
be careful:
- It is allowed to use the same variable name in different functions. They represent different objects, allocate different units, and do not interfere with each other.
- In the same source file, global variables and local variables are allowed to have the same name. Within the scope of local variables, global variables do not work.
- All functions are global by default, which means that all functions cannot have the same name. However, if it is a staitc function, the scope is file level, so different file static function names can be the same.
8.1. 7 Summary
8.2 memory layout
8.2. 1 memory partition
C code generates an executable program after four steps: preprocessing, compiling, assembling and linking.
Under Windows, a program is an ordinary executable file. The basic information of a binary executable file is listed below:
It can be seen from the above figure that before the program is run, that is, before the program is loaded into memory, the executable program has been divided into three pieces of information, namely code area (text), data area (data) and uninitialized data area (bss) (some people directly call data and bss static area or global area).
- Code area
Store the machine instructions executed by the CPU. Generally, the code area is shareable (that is, another executing program can call it). The purpose of making it shareable is to have only one copy of code in memory for frequently executed programs. The code area is usually read-only. The reason for making it read-only is to prevent the program from accidentally modifying its instructions. In addition, the code area also plans the relevant information of local variables.
- Global initialization data area / static data area (data section)
This area contains the global variables explicitly initialized in the program, the initialized static variables (including global static variables and local static variables) and constant data (such as string constants).
- Uninitialized data area (also known as bss area)
Stored are global uninitialized variables and uninitialized static variables. The data in the uninitialized data area is initialized to 0 or NULL by the kernel before the program starts execution.
Before the program is loaded into memory, the size of code area and global area (data and bss) is fixed and cannot be changed during program operation. Then, the executable program is run, and the system loads the program into memory. In addition to separating the code area (text), data area (data) and uninitialized data area (bss) according to the information of the executable program, the stack area and heap area are added.
- text segment
The executable code segment is loaded. All executable code is loaded into the code area. This memory cannot be modified during operation.
- Uninitialized data area (BSS)
The BSS segment of the executable file is loaded, and the location can be separated or close to the data segment. The life cycle of the data stored in the data segment (Global uninitialized and static uninitialized data) is the whole program running process.
- Global initialization data area / static data area (data segment)
The executable file data segment is loaded. The life cycle of the data stored in the data segment (Global initialization, static initialization data, text constant (read-only)) is the whole program running process.
- stack area
Stack is a first in and last out memory structure, which is automatically allocated and released by the compiler to store function parameter values, return values, local variables, etc. It is loaded and released in real time during the program running. Therefore, the life cycle of local variables is from the application to the release of the stack space.
- heap
Heap is a large container. Its capacity is much larger than that of stack, but it is not in the order of first in and last out. Used for dynamic memory allocation. The heap is located in memory between the BSS area and the stack area. It is generally allocated and released by the programmer. If the programmer does not release it, it will be recycled by the operating system at the end of the program.
8.2. 2 heap memory allocation and release
- malloc()
#include <stdlib.h> void *malloc(size_t size); Function: dynamic storage area in memory(Heap area)A piece with length of size A contiguous area of bytes that holds the type specified by the type specifier. The content of the allocated memory space is uncertain and is generally used memset initialization. Parameters: size: Need to allocate memory size(Unit: byte) Return value: Success: the starting address of the allocated space Failed: NULL
#include <stdlib.h> #include <stdio.h> #include <string.h> int main() { int count, *array, n; printf("Please enter the number of arrays to apply for:\n"); scanf("%d", &n); array = (int *)malloc(n * sizeof (int)); if (array == NULL) { printf("Failed to apply for space!\n"); return -1; } //Apply to space clearing 0 memset(array, 0, sizeof(int)*n); for (count = 0; count < n; count++) /*Assign a value to an array*/ array[count] = count; for (count = 0; count < n; count++) /*Print array elements*/ printf("%2d", array[count]); free(array); return 0; }
- free()
#include <stdlib.h> void free(void *ptr); Function: release ptr A piece of memory space pointed to, ptr Is a pointer variable of any type, pointing to the first address of the released area. Releasing the same memory space multiple times will result in an error. Parameters: ptr: The first address of the space to be released. The released area should be malloc The area allocated by the function. Return value: None
9. Composite type (custom type)
9.1 structure
9.1. 1 Overview
Array: describes an ordered set of data of the same type, which is used to process a large number of data operations of the same type.
Sometimes we need to combine different types of data into an organic whole. For example, a student has attributes such as student number / name / gender / age / address. Obviously, defining the above variables alone is cumbersome and the data is not easy to manage.
C language gives another type of construction data structure.
9.1. 2 Definition and initialization of structure variables
How to define structure variables:
- Declare the structure type before defining the variable name
- Define variables while declaring types
- Directly define structure type variables (no type name)
Structure type and structure variable relationship:
- Structure type: specifies a structure type, which is equivalent to a model, but there is no specific data in it, and the system does not allocate actual memory units.
- Structure variable: the system allocates space according to the structure type (internal member status).
//Definition of structure type struct stu { char name[50]; int age; }; //Define type first, then variable (common) struct stu s1 = { "mike", 18 }; //Define types and variables struct stu2 { char name[50]; int age; }s2 = { "lily", 22 }; struct { char name[50]; int age; }s3 = { "yuri", 25 }; 9.1.3 Use of structure members #include<stdio.h> #include<string.h> //Definition of structure type struct stu { char name[50]; int age; }; int main() { struct stu s1; //If it is a normal variable, operate the structure member through the point operator strcpy(s1.name, "abc"); s1.age = 18; printf("s1.name = %s, s1.age = %d\n", s1.name, s1.age); //If it is a pointer variable, operate the structure member through - > operation strcpy((&s1)->name, "test"); (&s1)->age = 22; printf("(&s1)->name = %s, (&s1)->age = %d\n", (&s1)->name, (&s1)->age); return 0; }
9.1. 4 structure array
#include <stdio.h> //Statistics of student achievement struct stu { int num; char name[20]; char sex; float score; }; int main() { //Define a structure array with 5 elements and initialize it struct stu boy[5] = { { 101, "Li ping", 'M', 45 }, { 102, "Zhang ping", 'M', 62.5 }, { 103, "He fang", 'F', 92.5 }, { 104, "Cheng ling", 'F', 87 }, { 105, "Wang ming", 'M', 58 }}; int i = 0; int c = 0; float ave, s = 0; for (i = 0; i < 5; i++) { s += boy[i].score; //final scoring if (boy[i].score < 60) { c += 1; //Count the scores of unqualified people } } printf("s=%f\n", s);//Print total score ave = s / 5; //Calculate average score printf("average=%f\ncount=%d\n\n", ave, c); //Print average score and number of failed students for (i = 0; i < 5; i++) { printf(" name=%s, score=%f\n", boy[i].name, boy[i].score); // printf(" name=%s, score=%f\n", (boy+i)->name, (boy+i)->score); } return 0; }
9.1. 5 structure sleeve structure
#include <stdio.h> struct person { char name[20]; char sex; }; struct stu { int id; struct person info; }; int main() { struct stu s[2] = { 1, "lily", 'F', 2, "yuri", 'M' }; int i = 0; for (i = 0; i < 2; i++) { printf("id = %d\tinfo.name=%s\tinfo.sex=%c\n", s[i].id, s[i].info.name, s[i].info.sex); } return 0; }
9.1. 6 structure assignment
#include<stdio.h> #include<string.h> //Definition of structure type struct stu { char name[50]; int age; }; int main() { struct stu s1; //If it is a normal variable, operate the structure member through the point operator strcpy(s1.name, "abc"); s1.age = 18; printf("s1.name = %s, s1.age = %d\n", s1.name, s1.age); //Two structural variables of the same type can be assigned to each other //Copy the value of s1 member variable to the memory of s2 member variable //s1 and s2 are just the same values of member variables. They are still two unrelated variables struct stu s2 = s1; //memcpy(&s2, &s1, sizeof(s1)); printf("s2.name = %s, s2.age = %d\n", s2.name, s2.age); return 0; }
9.1. 7 structure and pointer
1)Pointer to a normal structure variable #include<stdio.h> //Definition of structure type struct stu { char name[50]; int age; }; int main() { struct stu s1 = { "lily", 18 }; //If it is a pointer variable, operate the structure member through - > operation struct stu *p = &s1; printf("p->name = %s, p->age=%d\n", p->name, p->age); printf("(*p).name = %s, (*p).age=%d\n", (*p).name, (*p).age); return 0; }
2)Heap structure variable #include<stdio.h> #include <string.h> #include <stdlib.h> //Definition of structure type struct stu { char name[50]; int age; }; int main() { struct stu *p = NULL; p = (struct stu *)malloc(sizeof(struct stu)); //If it is a pointer variable, operate the structure member through - > operation strcpy(p->name, "test"); p->age = 22; printf("p->name = %s, p->age=%d\n", p->name, p->age); printf("(*p).name = %s, (*p).age=%d\n", (*p).name, (*p).age); free(p); p = NULL; return 0; }
3)Structure set primary pointer #include<stdio.h> #include <string.h> #include <stdlib.h> //Definition of structure type struct stu { char *name; //Primary pointer int age; }; int main() { struct stu *p = NULL; p = (struct stu *)malloc(sizeof(struct stu)); p->name = malloc(strlen("test") + 1); strcpy(p->name, "test"); p->age = 22; printf("p->name = %s, p->age=%d\n", p->name, p->age); printf("(*p).name = %s, (*p).age=%d\n", (*p).name, (*p).age); if (p->name != NULL) { free(p->name); p->name = NULL; } if (p != NULL) { free(p); p = NULL; } return 0; }
9.1. 8 structure as function parameters
1) Structure ordinary variables as function parameters
#include<stdio.h> #include <string.h> //Definition of structure type struct stu { char name[50]; int age; }; //Function parameters are structural ordinary variables void set_stu(struct stu tmp) { strcpy(tmp.name, "mike"); tmp.age = 18; printf("tmp.name = %s, tmp.age = %d\n", tmp.name, tmp.age); } int main() { struct stu s = { 0 }; set_stu(s); //pass by value printf("s.name = %s, s.age = %d\n", s.name, s.age); return 0; }
2) Structure pointer variable as function parameter
#include<stdio.h> #include <string.h> //Definition of structure type struct stu { char name[50]; int age; }; //The function parameter is a structure pointer variable void set_stu_pro(struct stu *tmp) { strcpy(tmp->name, "mike"); tmp->age = 18; } int main() { struct stu s = { 0 }; set_stu_pro(&s); //Address delivery printf("s.name = %s, s.age = %d\n", s.name, s.age); return 0; }
3) Structure array name as function parameter
#include<stdio.h> //Definition of structure type struct stu { char name[50]; int age; }; //void set_stu_pro(struct stu tmp[100], int n) //void set_stu_pro(struct stu tmp[], int n) void set_stu_pro(struct stu *tmp, int n) { int i = 0; for (i = 0; i < n; i++) { sprintf(tmp->name, "name%d%d%d", i, i, i); tmp->age = 20 + i; tmp++; } } int main() { struct stu s[3] = { 0 }; int i = 0; int n = sizeof(s) / sizeof(s[0]); set_stu_pro(s, n); //Array name passing for (i = 0; i < n; i++) { printf("%s, %d\n", s[i].name, s[i].age); } return 0; } 4)const Modifier structure pointer parameter variable //Definition of structure type struct stu { char name[50]; int age; }; void fun1(struct stu * const p) { //p = NULL; //err p->age = 10; //ok } //void fun2(struct stu const* p) void fun2(const struct stu * p) { p = NULL; //ok //p->age = 10; //err } void fun3(const struct stu * const p) { //p = NULL; //err //p->age = 10; //err }
9.2 Consortium (Consortium)
- A union is a type that can store different types of data in the same storage space;
- The memory length occupied by a consortium is equal to a multiple of the length of its longest member, which is also called a common body;
- The same memory segment can be used to store several different types of members, but only one of them works in each instant;
- The active member in the community variable is the last stored member. After saving a new member, the value of the original member will be overwritten;
- The address of a common body variable is the same as that of its members.
#include <stdio.h> //A consortium is also called a consortium union Test { unsigned char a; unsigned int b; unsigned short c; }; int main() { //Define common body variables union Test tmp; //1. The first address of all members is the same printf("%p, %p, %p\n", &(tmp.a), &(tmp.b), &(tmp.c)); //2. The community size is the size of the largest member type printf("%lu\n", sizeof(union Test)); //3. The assignment of one member will affect other members //The left is high and the right is low //Low address, high address tmp.b = 0x44332211; printf("%x\n", tmp.a); //11 printf("%x\n", tmp.c); //2211 tmp.a = 0x00; printf("short: %x\n", tmp.c); //2200 printf("int: %x\n", tmp.b); //44332200 return 0; }
9.3 enumeration
Enumeration: list the values of variables one by one. The values of variables are limited to the range of listed values.
Enumeration type definition:
enum Enumeration name { Enumeration value table };
- All available values, also known as enumeration elements, should be listed in the enumeration value table.
- The enumeration value is a constant and cannot be assigned with an assignment statement in the program.
- The lifting element itself is defined by the system as a numerical value representing the sequence number, starting from 0 and defined as 0, 1, 2
#include <stdio.h> enum weekday { sun = 2, mon, tue, wed, thu, fri, sat } ; enum bool { flase, true }; int main() { enum weekday a, b, c; a = sun; b = mon; c = tue; printf("%d,%d,%d\n", a, b, c); enum bool flag; flag = true; if (flag == 1) { printf("flag For true\n"); } return 0; }
9.4 typedef
typedef is a keyword of C language. It is used to define a new name for a data type (basic type or user-defined data type). New types cannot be created.
- Unlike #define, typedef is limited to data types, not expressions or concrete values
- #define occurs during preprocessing and typedef occurs during compilation
#include <stdio.h> typedef int INT; typedef char BYTE; typedef BYTE T_BYTE; typedef unsigned char UBYTE; typedef struct type { UBYTE a; INT b; T_BYTE c; }TYPE, *PTYPE; int main() { TYPE t; t.a = 254; t.b = 10; t.c = 'c'; PTYPE p = &t; printf("%u, %d, %c\n", p->a, p->b, p->c); return 0; }