Basic knowledge of C language entry [full version]

Table of contents

1. Data types and expressions

Representation of binary, octal and hexadecimal numbers in C language:

  • Binary : Binary is composed of two numbers, 0 and 1, and must start with 0b or 0B (case-insensitive) when used. For example: 0b101,0B001
    Note: The standard C language does not support binary notation, and some compilers have extended themselves to support binary numbers
  • Octal : Octal consists of eight numbers from 0 to 7, and must start with 0 when used (note that it is the number 0, not the letter o), for example: 015(13 in decimal), 0177777(65535 in decimal)
  • Hexadecimal : Hexadecimal consists of numbers 0~9, letters A~F or a~f (case-insensitive), and must start with 0x or 0X (case-insensitive) when used, for example: (decimal 43), (decimal 0X2A65535 0xffff)

1. Basic type

  • Integer (int)
  • Character type (char)
  • Real (float)
    • Single precision type (float)
    • Double type (double)
  • Enumeration type
    The following is a detailed type description:
type type specifier byte range of numbers
character type char 1 C character set
basic integer int 4 -32768~32767
short integer short int 2 -32768~32767
long integer long int 4 -214783648~-214783647
unsigned integer unsigned int 4 0~65535
unsigned long unsigned long 4 0~4294967295
single precision real float 4 10-38~1038
double precision real double 8 10-308~10-308

2. Construction type

1) Array type

Array: A collection of similar data elements arranged in sequence

  • One-dimensional array:类型说明符 数组名[数组长度];
  • Two-dimensional/multidimensional arrays: 类型说明符 数组名[行数][列数];Multidimensional arrays and so on
  • Character array: char 数组名[数组长度];C language does not have a string type, and strings are usually represented by character arrays

Array definition: 类型说明符 数组名[长度];
Array reference:
One-dimensional array 数组名[索引];     Two-dimensional array 数组名[行索引][列索引];
Note: Indexes start from 0
Array assignment:
1. Assign initial value when defining: int a[10]={1,2,3,4,5,6,7,8,9,10};or int a[]={1,2,3,4,5,6,7,8,9,10};
2. Define first, then assign: int a[10];a = {1,2,3,4,5,6,7,8,9,10};
character array assignment:
1. char Hello[] = {'H','e','l','l','o'};
2. char Hello[] = "Hello";
Note: The second method of character array assignment takes one more character than the first method, because the second method will add one at the end of the character array as a string \0terminator

Tip: When assigning an array, if the number of given values ​​is less than the length of the array, the system will fill with 0 by default

Example:

#include <stdio.h>

int main() {
    
    
    //=====================一维数组===============
    int a[5] = {
    
    1, 2}; // a={1,2,0,0,0}
    int b[] = {
    
    1, 2, 3, 4, 5};// b={1,2,3,4,5}
    int c[10];// 没有赋初始值系统会自动赋值一个无意义的数字,可以自行printf输出查看
    printf("a第二个元素:%d\nb第一个元素:%d\n", a[1], b[0]);

    //=====================二维数组===============
    int aa[2][3] = {
    
    1, 2, 3, 4, 5, 6};// C语言是按行编址,所以可以这样赋值
    int bb[2][3] = {
    
    
            {
    
    1, 2, 3},
            {
    
    4, 5, 6}
    };
    //aa和bb这两个数组是相同的
    printf("aa第1行第1列元素:%d\n", aa[0][0]);
    printf("bb第1行第2列元素:%d\n", bb[0][1]);
    //=====================字符串===============
    char name[8] = {
    
    'x', 'i', 'a', 'o', 'm', 'i', 'n', 'g'};
    char name2[] = "xiaohong";
    printf("第一个名字:%s第二个名字:%s", name, name2);
    return 0;
}

2) Structure type

3) Union type

3. Constants

There are two ways to define constants in C language. If we want to define a constant TEMP of type int, the value is 1:

  • Predefined commands:#define TEMP = 1
  • const keyword:const int TEMP = 1

4. Operation expression

1) Arithmetic operation expressions:

  • Plus: +
  • reduce:-
  • take:*
  • remove:/
  • Surplus: %
  • Increment: ++
  • Decrease:--

Note: When auto-increment and auto-decrement are combined with assignment, if the operator is on the left, auto-increment or auto-decrement will be performed first, see the following example:

void test1(){
    
    
int a = 1;
int b = ++a; //结果是b=2
}

void test2(){
    
    
int a = 1;
int b = a++; //结果是b=1
}

2) Relational operation expression:

  • Equal to: ==
  • greater than:>
  • Greater than or equal to: >=
  • less than: <
  • Less than or equal to: <=
  • Not equal to: !=

3) Logical operators:

In C language, non-zero is true

  • and:&&
  • or: ||
  • No:!

4) Bitwise operators:

  • Bit AND: &
    performs logical AND operation on each bit, 0 means false, 1 means true:0011 & 1111 = 0011
  • Bit OR: |
    Logical OR operation on each bit, 0 means false, 1 means true:0011 | 1111 =1111
  • Bit NOT: ~
    performs a logical NOT operation on each bit, 0 means false, 1 means true:~1111 =0000
  • Bit XOR: ^
    performs a logical XOR operation on each bit, 0 means false, 1 means true:0011 ^ 1111 =0011
  • Left shift: <<
    The high bit overflows and discards, and the low bit is insufficient to fill in 0:01100100 << 2 = 10010000
  • Move right: >>
    • Positive number: 0 is added to the high bit, and the overflow of the low bit is discarded:01111111 >> 4 = 00000111
    • Negative number: 1 is added to the high bit, and the low bit is overflowed and discarded:11111111 >> 4 = 11111111

Two, C language statement

1. Expression statement

Definition: A statement consisting of an expression followed by a semicolon: x + y = z;

2. Function call statement

Definition: function name, actual parameters and semicolons: function name (parameter);

3. Control Statements

1) Conditional judgment statement:

  • if statement: single condition judgment statement
// 用法
if (条件表达式){
    
    
	// 条件满足
	要执行的语句
}
  • if...else... statement: conditional branch statement
// 用法
if (条件表达式){
    
    
	// 条件满足
	要执行的语句
}else{
    
    
	// 条件不满足
	要执行的语句
}
  • if...else if...else... statement: multi-conditional branch statement
// 用法
if (条件表达式1){
    
    
	// 满足条件表达式1
	要执行的语句;
}else if (条件表达式2) {
    
    
	// 满足条件表达式2
	要执行的语句;
}else if (条件表达式3) {
    
    
	// 满足条件表达式3
	要执行的语句;
}

...

else if (条件表达式n) {
    
    
	// 满足条件表达式n
	要执行的语句;
}else{
    
    
	// 所有条件表达式都不满足
	要执行的语句;
}
  • switch statement: switch statement, generally used with the case keyword
switch(表达式)
{
    
    

	case 常量1// 如果表达式的值等于常量1,执行下面的语句1
		语句1 ;
		break;

	case 常量2// 如果表达式的值等于常量2,执行下面的语句2
		语句2;
		break;

		...

	case 常量n:
		// 如果表达式的值等于常量n,执行下面的语句n
		语句n;
		break;

	default:
		// 默认执行的语句,如果没有通过上面的开关语句退出,就会执行下面的语句n+1
		语句n+1;
		//break; // default可以省略break;因为它本身就是最后执行,执行完就会退出开关语句。

}

Note: If the switch statement does not have a break, it will be executed until the end.

2) Loop execution statement:

  • for statement

Structure:
for (expression 1; expression 2; expression 3) { statement; } Loop logic: step1: first execute expression 1 step2: then execute expression 2, step3: if the result of step2 is true, execute the statement, otherwise exit the loop step4: if step3 does not exit the loop, then execute expression 3 step5: repeatedly execute step2-step4 until the loop exits







//用法
for (循环变量赋初值;循环条件;循环变量增量){
    
    
	执行语句;
}
  • while statement

Conditional loop statement, loop execution when the loop condition is met

//用法
while (循环条件){
    
    
	执行语句;
}
  • do while statement

The difference with the while loop: do...while will execute the statement in the loop body first, and then make a conditional judgment, that is to say, do...while will execute the statement in the loop body at least once

//用法
do{
    
    
	执行语句;
}while (循环条件);

3) Turn to statement:

  • continue: The continue statement is generally used in a loop structure. Its function is to skip the current loop. When the loop statement is executed to continue, it will not continue to execute downwards, but will skip the current loop and directly execute the next loop.
  • break: Break statement, generally used in loop structure, its function is to terminate the loop, when the break statement is executed, it will exit the loop immediately.
  • return: Jump out of the function statement, used to jump out of the function and return a value.
  • goto: forced to go to the statement (deprecated)
//用法
int main(){
    
    
	int a=1;
	int b=5;
	loop: if (a<b){
    
    
		printf("%d\n",a);
		a++;
		goto loop;
	}
	return 0;
}

Output result:
1
2
3
4
Explanation: The goto statement is generally used to combine with the if statement to form a loop structure, and a marker (loop) needs to be defined first to indicate where the goto turns to.

4. Compound statement

Definition: Enclose multiple statements in braces to form a compound statement

{
    
    
	int a = 1;
	a++;
	int b = a + 1;
}

5. Empty statement

Definition: A statement consisting only of semicolons is called an empty statement

;

6. Case

1) Helen's formula

Find the area from the three sides of a triangle: S= p ( a − p ) ( b − p ) ( c − p ) \sqrt{p(ap)(bp)(cp)}p(ap)(bp)(cp)

S: area p: 1/2 of the perimeter a, b, c: the lengths of the three sides of the triangle

#include "stdio.h"
#include "math.h"

int main(){
    
    
    float a;
    float b;
    float c;
    float area;
    float p;
    printf("请输入构成三角形的三条边的长度:");
    scanf("%f,%f,%f", &a, &b, &c);
    p = (a+b+c)/2;
    area = sqrt(p*(a-p)*(b-p)*(c-p));
    printf("三角形面积是:%f",area);
    return 0;
}

2) Quadratic equation in one variable

#include <stdio.h>
#include "math.h"

int main() {
    
    
    float a,b,c;
    float p,x1,x2;
    printf("请输入一元二次方程的3个系数a,b,c:ax^2+bx+c=0(a≠0)\n");
    scanf("%f,%f,%f",&a,&b,&c);
    p = sqrt(b*b-4*a*c);
    x1 = (-b+p)/(2*a);
    x2 = (-b-p)/(2*a);
    printf("方程的解为:x1=%f,x2=%f",x1,x2);
    return 0;
}

3. Function

1. The concept of function

A function is a block of code that implements a certain function

  • Library function: provided by the C system, the user does not need to define, and does not need to specify the type in the program, just include the header file with the prototype of the function in front of the program, and then call it directly in the program.
  • User Defined Function: A function written by the user as needed. For a user-defined function, not only the function itself must be defined in the program, but also the type of the called function must be declared in the calling function module before it can be used.

2. How to define the function

  • No-argument function:
类型标识符 函数名() {
	声明部分;
	语句;
}
  • With parameter function:
类型标识符 函数名(形参1,形参2,形参3...形参n) {
	声明部分;
	语句;
}
  • Example: Two functions are defined below, the first HelloWorld is a function without parameters, and its function is to output a "Hello World!"
//void HelloWorld();
//int FindMax(int a,int b);
//上面是对函数进行声明,函数的调用必须先定义,否则编译不通过,如果定义在调用函数之后,需要先声明

void HelloWorld() {
    
    
    printf("Hello World!");
}

int FindMax(int a, int b) {
    
    
    int max;
    max = a >= b ? a : b;
    return max;
}

int main(){
    
    
	HelloWorld();
    int a = 5;
    int b = 10;
    int c;
    c = FindMax(a, b);
    printf("\n最大数为:%d\n", c);
    return 0;
}

3. Function parameters

  • Formal parameters: Formal parameters appear in the function definition and can be used in the entire function body, but cannot be used outside the function.
  • Actual parameter: The actual parameter is the parameter passed when calling the function in the calling function.
  • Parameter passing: The parameters of the function are passed from the actual parameters of the calling function to the formal parameters of the called function, so the order and type of actual parameters must be consistent.

4. The return value of the function

The return value of a function is a value of the same type as the return type defined in the function declaration. If no return type is defined in the function declaration, it defaults to the int type.
For example, here is a simple C function that returns an integer value:

int max(int a, int b)
{
    
    
    if (a > b) {
    
    
        return a;
    } else {
    
    
        return b;
    }
}

In this example, the function max() defines two parameters a and b of type int, and judges their size relationship inside the function body. If a is greater than b, the function returns the value of a; otherwise, the function returns the value of b.

In addition, if the return value of void type is defined in the function declaration, it means that the function will not return any value. In this case, the return statement cannot be used inside the function body to return a value. For example:

void print_hello()
{
    
    
    printf("Hello, world!\n");
}

In this example, the function print_hello() does not need to return any value, so the return type defined in the declaration is void.

5. Function call

  • The general form of the call is:函数名(实参);
  • Declaration and function prototype of the called function: Before calling a function in the calling function, the called function should be described (declared), which is the same as the variable description before using the variable. The purpose of describing the called function in the calling function is to let the compilation system know the type of the return value of the called function, so that the returning value can be processed accordingly in the calling function according to this type.
    Its general form is: 类型说明符 被调函数名(类型 形参,类型 形参...);or 类型说明符 被调函数名(类型,类型...);

6. Global variables and local variables

Scope: Indicates the scope in which a variable works, for example:

{
     
     
	int a = 1; //a的作用域就是这个代码块,在代码块外部就无法访问变量a
}

1) Global variables

  • Definition: A global variable is also known as an external variable, which is a variable defined outside a function. It does not belong to any function, it belongs to a source program file. Its scope is the entire source program.
  • Use: To use a global variable in a function before the global variable definition, you need to use keywords externto describe the global variable, declare a variable as a global variable before it can be used; to use a global variable in a function after the global variable definition, you can omit the externkeyword, and you can use it without specifying the global variable.
int a = 5; // 此处a为全局变量

int main(void){
    
    
	int extern a; // 全局变量说明,声明a是一个全局变量,此处在a定义之后,可以省略该说明
	printf("%d", a); //输出结果为5
}

2) Local variables

  • Definition: Local variables are also known as internal variables. A local variable is a variable defined inside a function, and its scope is limited to the inside of the function. Local variables can only be used inside the function and cannot be accessed outside the function.
int main(void){
    
    
	int a = 5; // 这是一个局部变量,a的作用域范围是main函数内,在函数外无法使用
	print("%d", a);
	a++;
}
print("%d", a);//全局作用域内找不到变量a,编译不通过

7. Static variables and register variables

1) Static variables

  • Definition: A static variable is a variable that does not disappear after the function call ends but retains its original value. If you want it to retain the value of a certain variable after a function call ends, declare the variable as a static variable with keywords static.
// 定义一个自增函数,初始化局部静态变量a为0,每调用一次,a自增1
int Add() {
    
    
    static int a = 0;
    a++;
    return a;
}

int main(){
    
    
	print("%d", Add());// 输出结果为1
	print("%d", Add());// 输出结果为2
	return 0;
}

2) Register variables

  • Definition: A register variable is a variable placed in a CPU register. The CPU register can be understood as the memory space of the CPU, just like the memory of a computer, and the operation speed in the register is very fast. Use registerkeyword declarations.
  • Notice:
    • Only local automatic variables (non-static variables) and formal parameters can be used as register variables
    • The number of registers in a computer system is limited, and any number of register variables cannot be defined
    • A local static variable cannot be defined as a register variable
#include "stdio.h"

// 这是一个计算n的阶乘的函数,将局部变量i和f声明为寄存器变量
int fac(int n) {
    
    
    register int i, f = 1;
    for (i = 1; i <= n; i++) {
    
    
        f = f * i;
    }
    return f;
}

int main() {
    
    
    int i;
    for (i = 0; i <= 5; i++) {
    
     
        printf("%d!=%d\n", i, fac(i)); 
    }
    return 0;
}

8. Preprocessing commands

Preprocessing refers to the work done before the first pass of compilation (lexical scanning and parsing). Preprocessing is an important function of C language, which is completed by the preprocessing program.
C language provides a variety of preprocessing functions, such as macro definition, file inclusion, conditional compilation, etc.

1) Macro definition

C language can be used to #definedefine macros (similar to constants), and the program will replace all macro names in the source program with the results of macro definitions during compilation.
The macro definition is completed by the macro definition command in the source program. Macro substitution is done automatically by the preprocessor.

  • No-argument macro definition: #define 标识符 字符串("string" can be constant, expression, format string, etc.)

All macro names appearing in the source program will be replaced with the string defined by the macro.
For example:

#include <stdio.h>

#define PI 3.1415926
#define M (a+a)

int main(void) {
     
     

  double a = 1.0;
   double b;
   b = 2*M + PI; // 等同于2*(a+a) + 3.1415926
   printf("%f", b);
   return 0;
}
  • Macro definition with parameters: #define 宏名(形参1,形参2,形参3,...形参n) 字符串("string" can be constant, expression, format string, etc.)

Similar to defining an anonymous function

>#include <stdio.h>

#define S(x,y) x*y // S表示矩形面积,x,y分别表示长宽

int main(void) {
     
     

  double a = 3.0,b = 4.0;
   double s;
   s = S(a,b); // 等同于a*b
   printf("%f", s);
   return 0;
}

2) The file contains

The function of the file include command is to insert the specified file into the position of the command line instead of the command line, so as to link the specified file and the current source program file into a source file.
The form of file inclusion is: #include "文件名"or #include <文件名>
The difference between the above two forms: using angle brackets means searching in the directory of the containing file (the containing directory is set by the user when setting the environment), not in the directory of the source file; using double quotation marks means searching in the current directory of the source file first, and if not found, then searching in the directory of the containing file.

3) Conditional compilation

The preprocessor provides the functionality of conditional compilation. Different program parts can be compiled according to different conditions, thus producing different object code files.

There are three forms of conditional compilation:

  • The first one: if the identifier has been #definedefined by the command, compile segment 1; otherwise, compile segment 2.
#ifdef 标识符
	程序段 1
#else
	程序段 2
#endif
  • The second type: if the identifier has not been #definedefined by the command, compile the program segment 1, otherwise compile the program segment 2.
#ifndef 标识符 
	程序段 1 
#else 
	程序段 2 
 #endif
  • The third type: if the value of the constant expression is true (not 0), then program segment 1 is compiled, otherwise program segment 2 is compiled.
#if 常量表达式
	程序段 1
#else 
	程序段 2
#endif

4. Pointer

A pointer refers to the address of a storage unit. For example, defining a variable int a = 1;pointing to a pointer to a variable is the address of a in memory.

1. Variable pointer & pointer variable

  • Variable pointer: It is the memory address of the variable.
  • Pointer variable: A variable that stores the address of a variable.
    Explanation: For example, there is a variable a, the address of variable a is p, and p is the pointer of variable a. Now let's assume a variable b, and then assign p to the variable b, then the variable b is a pointer variable (literally, a variable that stores pointers).

1) Definition of pointer variable

类型说明符* 变量名;

The type specifier indicates the variable type pointed to by the pointer, in other words, the value of the pointer variable must be the address of a variable of what type

For example:

int* p1; //定义一个int类型的指针变量,指向的变量类型也必须是int
char* p2; //定义一个char类型的指针变量,指向的变量类型也必须是char
double* p3; //定义一个double类型的指针变量,指向的变量类型也必须是double

2) Pointer operation

  • &: take address operator

    &变量名Represents the address of the variable, that is, the pointer to the variable

    int a = 123;
    int* p = &a; //取变量a的地址赋值给指针变量p
    
  • *: pointer operator (or "indirect access" operator)

    *指针变量Represents the value of the variable pointed to

    int a = 123;
    int* p = &a; //取变量a的地址赋值给指针变量p
    printf("%d",*p); //输出123,*p表示取a的值
    

2. Array pointer & pointer array

1) Pointer to the array

The pointer of the array refers to the first address of the array.
Glossary:An array is made up of a contiguous block of memory cells. The array name is the first address of this continuous memory unit, and also the address of the first element in the array.

int array[] = {
     
     1,2,3,4,5,6};
int* pA = array; // 数组名就是数组的指针
int* pB = &array[0]; // 数组的第一个元素的地址就是数组的指针

pointer pA and pointer pB are equal

2) Array of pointers

An array whose elements are pointers is an array of pointers.
Definition method: 类型说明符* 数组名[数组长度](same as ordinary array definition method, the only difference is *)

int main() {
     
     
   int a=1,b=2,c=3,d=4,e=5;
   int* Int[5] = {
     
     &a,&b,&c,&d,&e}; // 这是一个整型指针数组
   // 字符串在C语言中是字符数组,所以一个字符串相当于一个字符数组,字符串本身就等于字符数组的指针(首地址)
   char* String[] = {
     
     "Test1","Test2","Test3","Test4","Test5"}; // 这是一个字符型的指针数组
   for (int i = 0; i < 5; ++i) {
     
     
       printf("%p\n",String[i]); // 这里输出的就是每个字符串的指针
   }
   return 0;

3. String pointer

There is no string type in C language. Strings in C language are stored in character arrays. The
pointer of the string is the pointer of the character array, which is the first address of the character array.

Two definition forms of C language strings:

  • Array form: char string[] = {'H','e','l','l','o','\0'};orchar string[] = "Hello";
  • Pointer form: char* string = "Hello";(equivalent to {'H','e','l','l','o','\0'})

4. Function pointer & pointer function

1) pointer to function

In C language, a function always occupies a continuous memory area, and the function name is the first address (function pointer) of the memory area occupied by the function.

  • Definition of function pointer:类型说明符 (*指针变量名)(实参类型);
int (*p)(); // 定义一个函数指针p
int Function(){
    
    
    printf("test");
}
p = Function; // 将Function函数的入口地址赋值给函数指针变量p

Note: The definition of function pointers is different from that of variable pointers

  • Function pointer call:(*指针变量名) (实参表);
int FindMax(int a, int b){
    
    
    return a > b ? a : b;
}

int main() {
    
    
    int (*p)(int, int) = FindMax;
    int max = p(5,10);
    printf("%d",max);

    return 0;
} 

2) Pointer function

A function whose function type is a pointer is a pointer function (the function type refers to the type of the function return value)
definition:

类型说明符* 函数名(参数){
   执行语句;
   return 对应类型的指针;
}

Example: The pointer function is defined below, its function is to randomly generate an array and return the pointer of the array

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int* GetNumber(){
    
    
    static int array[10];
    srand((unsigned)time(NULL));
    for (int i = 0; i < 10; ++i) {
    
    
        array[i] = rand();
        printf("%d\n",array[i]);
    }
    return array;
}

int main() {
    
    
    int* p = GetNumber();
    printf("===================================\n");
    for (int i = 0; i < 10; ++i) {
    
    
        printf("%d\n",p[i]);
    }

5. Pointer to Pointer

The pointer to the pointer means literally. If there is a variable a, the pointer of variable a is represented by p1, and p1 is assigned to a variable b, and the pointer of variable b is represented by p2. Now assign p2 to a variable c, which is the pointer to the pointer.

int a = 2333;
int* b = &a;
int** c = &b;

To access the value of the pointer to the pointer, use **, such as the pointer c above, the access method is**c

5. Structures and Unions

1. Structure

The structure is similar to the class concept in some object-oriented languages ​​(Python, C#, Java), that is, a set of data consists of multiple member data, and the member data can bebasic typeorconstruction type, must be defined before using the structure.

A structure is a data type composed of several members of different data types. Each member of a structure can have a different data type and name. Using a structure can combine information of multiple different data types into a single logical unit, which can be easily manipulated.

1) Definition of structure

  • Define the struct keyword:struct
  • Definition form:struct 结构名 {成员数据};
// 下面定义了一个名为Person的结构体,Person包含有一个人的姓名、年龄、性别、身高、住址信息
struct Person{
    
    
    char* name;
    int age;
    char sex;
    double height;
    char address[200];
};

2) Usage of structure

  • Representation of structure member variables: 结构名.变量名or(*结构指针).变量名/(*结构指针)->变量名
struct Person{
    
    
    char* name;
    int age;
    char sex;
    double height;
    char address[200];
};

int main() {
    
    
    struct Person man; // 结构体变量实例化
    struct Person woman; // 结构体变量实例化
    struct Person* pW = &woman; // 实例化一个结构体指针变量
    man.name; // 结构体变量直接表示
    man.sex;
    (*pW).name; // 结构体指针变量表示
    pW->sex; // 结构体指针变量表示
    return 0;
}
  • Assignment of structure variables: directly assign values ​​to member variables, and note that array types cannot be assigned directly.
#include <stdio.h>
#include <string.h>

// 下面定义了一个名为Person的结构体,Person包含有一个人的姓名、年龄、性别、身高、住址信息
struct Person{
    
    
    char* name;
    int age;
    char sex;
    float height;
    char address[200];
};

int main() {
    
    
    struct Person man;
    struct Person woman;
    struct Person* pW = &woman;
    man.name = "小明"; // 结构体变量赋值
    man.sex = 'M';
    man.age = 18;
    man.height = 1.78f;
    strcpy(man.address,"四川省成都市");
    (*pW).name = "小红"; // 结构体变量赋值
    (*pW).sex = 'W';
    pW->age = 19;
    pW->height = 1.68f;
    strcpy(pW->address,"四川省绵阳市"); // 数组类型不能直接赋值
    printf("姓名:%s\n年龄:%d\n性别:%c\n身高:%.2fm\n地址:%s\n",man.name,man.age,man.sex,man.height,man.address);
    printf("==============================================================================================\n");
    printf("姓名:%s\n年龄:%d\n性别:%c\n身高:%.2fm\n地址:%s\n",woman.name,woman.age,woman.sex,(*pW).height,pW->address);
    return 0;
}

2. Commonwealth (union)

A union is a special structure whose members share the same memory space. Each member of the union can have different data types, but they share the same memory space, so only one member's value can exist at the same time. The main purpose of the union is to perform type conversion between different data types or to save memory space.

1) Definition of Community

  • Define the struct keyword:union
  • Definition form:union 共用体名 {成员数据};
#include <stdio.h>
#include <string.h>

union data {
    
    
    int i;
    float f;
    char str[20];
};

int main() {
    
    
    union data mydata; // 实例化一个共用体变量

    mydata.i = 10;
    printf("mydata.i = %d\n", mydata.i);

    mydata.f = 3.14f;
    printf("mydata.f = %f\n", mydata.f);

    strcpy(mydata.str, "Hello");
    printf("mydata.str = %s\n", mydata.str);

    return 0;
}

In this example, we define a dataunion named that contains an integer variable i, a float variable f, and a character array str. In the mainfunction, we define a mydatacommon variable, which can be used to store intor type data.floatchar

Since all member variables share the same memory space, when setting mydata.fand mydata.str, mydata.ithe value of is overwritten. this is alsoA characteristic of the union: at any time, only one member variable is valid.

2) Usage of the union

Main purpose: perform type conversion between different data types or save memory space.

#include <stdio.h>
#include <string.h>

union data {
    
    
    int i;
    float f;
    char* s;
    char c;
};

int main() {
    
    
    union data temp; // 定义一个共用体temp
    temp.i = 10;
    printf("temp = %d\n",temp.i);
    printf("data中i的内存地址:%p\n",&temp.i);
    printf("data中f的内存地址:%p\n",&temp.f);
    printf("data中s的内存地址:%p\n",&temp.s);
    printf("data中c的内存地址:%p\n",&temp.c);
    // 可以看出共用体的所有成员指向的是同一块内存空间
    printf("=========================================================\n");
    temp.s = "测试";
    printf("temp = %s\n",temp.s);
    printf("data中i的内存地址:%p\n",&temp.i);
    printf("data中f的内存地址:%p\n",&temp.f);
    printf("data中s的内存地址:%p\n",&temp.s);
    printf("data中c的内存地址:%p\n",&temp.c);
    printf("=========================================================\n");
    temp.f = 3.14159f;
    printf("temp = %f\n",temp.f);
    printf("data中i的内存地址:%p\n",&temp.i);
    printf("data中f的内存地址:%p\n",&temp.f);
    printf("data中s的内存地址:%p\n",&temp.s);
    printf("data中c的内存地址:%p\n",&temp.c);
    printf("=========================================================\n");

    //通过上面的例子,如果把temp看做一个没有定义类型的变量,那么他就是个可变类型的变量


    return 0;
}

3. Enumeration

Enumeration (Enumeration) is a custom data type, which allows the definition of a set of named constants. A variable of enumeration type can only be assigned a value in the enumeration list, and these values ​​are called enumeration constants. Enumerated types are a very convenient way to organize and describe constants.

1) Definition of enumeration

  • Define enum keywords:enum
  • Define the form of the enumeration: enum 枚举名称 {枚举常量列表};(the value of the enumeration constant is considered to be int type or unsigned int type, and the default enumeration variable value is incremented from 0)
enum color {
    
    
    RED,
    GREEN,
    BLUE
};
/*上面定义了一个三种颜色的枚举,三种枚举默认值为RED=0,GREEN=1,BLUE=2*/
// 下面定义一个性别的枚举,并给枚举值进行自定义
enum sex {
    
    
    MAN = 1,
    WOMAN = 2
}

2) Usage of enumeration

Enums are often used to define a set of constant options

#include <stdio.h>
#include <string.h>

enum week {
    
    
    Mon,
    Tue,
    Wed,
    Thu,
    Fri,
    Sat,
    Sun
};

int main() {
    
    
    enum week today;
    today = Mon;
    switch (today) {
    
    
        case Mon:
            printf("今天是周一");
            break;
        case Tue:
            printf("今天是周二");
            break;
        case Wed:
            printf("今天是周三");
            break;
        case Thu:
            printf("今天是周四");
            break;
        case Fri:
            printf("今天是周五");
            break;
        case Sat:
            printf("今天是周六");
            break;
        case Sun:
            printf("今天是周日");
            break;
    }
    return 0;
}

4. Dynamic memory allocation

There are four commonly used memory management functions in C language: malloc, calloc, realloc, free
where the function to apply for space is malloc, calloc; the function to readjust the size of the space is realloc; the function to release space isfree

1)malloc

Role : used to allocate a specified size of memory space on the heap,random content, function prototype: void* malloc(size_t size);
parameters :

  • size: the size of the allocated space (bytes)

Return value : the first address of the allocated memory space, if the allocation fails, return a NULL pointer
Note: The return value type is void*, which needs to be converted to the corresponding type when used

The following is an example: allocate a space to store a specified number of numbers, and sum the numbers

#include <stdio.h>
#include <stdlib.h>

int main() {
    
    
    int* ptr; // 定义一个指针变量
    int n, sum = 0; // 初始化元素个数与元素总和

    printf("输入要保存的元素个数: ");
    scanf("%d", &n);

    ptr = (int*) malloc(n * sizeof(int)); // 分配一块足够存储n个int类型数字的内存空间,将指针强制转换为int类型

    if(ptr == NULL) {
    
    
        printf("内存空间分配失败!\n");
        exit(1);
    }

    printf("输入保存的元素:\n");
    for(int i = 0; i < n; i++) {
    
    
        scanf("%d", &ptr[i]);
        sum += ptr[i];
    }

    printf("所有元素累加总和为:%d\n", sum);

    free(ptr);// 释放内存空间ptr

    return 0;
}

2)calloc

Function : used to allocate a specified amount and size of memory space on the heap,The content is initialized to 0.
Its function prototype is: void* calloc(size_t num, size_t size);
parameters :

  • num: the number of allocated space blocks (how many blocks of space need to be allocated)
  • size: the size of each space (bytes)

Return value : the first address of the allocated memory space, if the allocation fails, return a NULL pointer
Note: The return value type is void*, which needs to be converted to the corresponding type when used

Also using the above example:

#include <stdio.h>
#include <stdlib.h>

int main() {
    
    
    int* ptr; // 定义一个指针变量
    int n, sum = 0; // 初始化元素个数与元素总和

    printf("输入要保存的元素个数: ");
    scanf("%d", &n);

    ptr = (int*) calloc(n, sizeof(int)); // 分配n块足够存储1个int类型数字的内存空间,将指针强制转换为int类型

    if(ptr == NULL) {
    
    
        printf("内存空间分配失败!\n");
        exit(1);
    }

    printf("输入保存的元素:\n");
    for(int i = 0; i < n; i++) {
    
    
        scanf("%d", &ptr[i]);
        sum += ptr[i];
    }

    printf("所有元素累加总和为:%d\n", sum);

    free(ptr);// 释放内存空间ptr

    return 0;
}

3)realloc

Role : used to reallocate the size of the allocated memory. Its function prototype is: void* realloc(void* ptr, size_t size);
parameters :

  • ptr: original memory space address
  • size: reallocate memory space size

Return value : the first address of the allocated memory space, if the allocation fails, return a NULL pointer
Note: The return value type is void*, which needs to be converted to the corresponding type when used

Explanation: reallocThe reallocation is adjusted on the basis of the original address. If the size of the space is expanded, when the new space size exceeds the range that the original space can expand (for example, a space occupies 4 bytes, now the space a needs to be extended to 8 bytes, and in this continuous memory, the 7th byte has been allocated, so this space can only be 6 bytes at most), the system will find a large enough space as the new space, and then copy the data in the original space to release the original space, that is, the pointer will be changed, and the value will be changed. There will be no change; if the size of the space is reduced, the memory space after the adjustment of the original space will be released.

Also use the above example to modify:

#include <stdio.h>
#include <stdlib.h>

int main() {
    
    
    int* ptr; // 定义一个指针变量
    int n,m, sum = 0; // 初始化元素个数与元素总和

    printf("输入要保存的元素个数: ");
    scanf("%d", &n);

    ptr = (int*) calloc(n, sizeof(int)); // 分配n块足够存储1个int类型数字的内存空间,将指针强制转换为int类型

    if(ptr == NULL) {
    
    
        printf("内存空间分配失败!\n");
        exit(1);
    }

    printf("输入保存的元素:\n");
    for(int i = 0; i < n; i++) {
    
    
        scanf("%d", &ptr[i]);
        sum += ptr[i];
    }
    m = n+2;
    ptr = (int*)realloc(ptr,m*sizeof(int)); // 重新分配一块足够存储m个int类型数字的内存空间
    printf("输入新增的元素:\n");
    for(int i = n; i < m; i++) {
    
    
        scanf("%d", &ptr[i]);
        sum += ptr[i];
    }

    printf("所有元素累加总和为:%d\n", sum);

    free(ptr);// 释放内存空间ptr

    return 0;
}

4)free

Function : used to release the allocated memory space. Its function prototype is: void free(void* ptr);
parameters :

  • ptr: the address of the space that needs to be released

Return value : no return value

5. Bit fields

The C language allows specifying the length of its members in a structure in units of bits (Bit). This structure member in units of bits is called a "bit segment" or "bit field". Bit fields can only be of type int, unsigned int, or signed int. int is signed by default.
The main purpose of the bit field: to save memory space. For example, switch control only needs 0 and 1, then only 1 bit is needed to represent binary 0 and 1, and a byte has 8 bits. Using a bit field can only use one of the bits in a byte.

  • Basic definition:
struct 位域名称 {
    
    
    位域列表;
}
  • Example: The following defines a date structure, including member variables year, month, and day. We use four digits to represent the year, and only need 14 digits at most. We only need four digits to represent January-December, and we only need to use 6 digits to fully represent 1-31 days.
#include <stdio.h>

struct Date{
    
    
    unsigned int year;
    unsigned int month;
    unsigned int day;
};

struct Date2{
    
    
    unsigned int year : 14;
    unsigned int month : 4;
    unsigned int day : 6;
};

int main() {
    
    
    printf("Date占用字节数:%llu\n", sizeof(struct Date));
    printf("Date2占用字节数:%llu\n", sizeof(struct Date2));
    return 0;
}

Output result:

Date占用字节数:12
Date2占用字节数:4

It can be seen from the above results that the use of bit fields can save memory space.
Note: The number of digits of a bit field cannot exceed the maximum number of digits of the basic type to which it is attached. For example, a member of unsigned int type has 4 bytes, and one byte is 8 bits. It can only store 32 bits at most, and the number of digits of a bit field cannot exceed 32 (different compiler basic types occupy different sizes of space)

6. File operation

1. The concept of files

A file is an ordered data set, and the name of the data set is called the file name. There are two types of files, one is ordinary files, such as txt files, C language source program files, header files, etc. that exist on the disk;

2. File pointer

The C language uses a pointer variable to point to a file, and operates the file by manipulating the pointer.
Definition of file pointer:FILE *变量名;

FILEIn fact, it is a structure defined by the system, which contains information such as file name, file status, and current location of the file (you don’t need to care about the details of the structure when writing a program FILE)

File location pointer: The file location pointer indicates the location pointer (head, current location, end, etc.) in the file. Note that it is different from the file pointer. The file pointer points to the entire file

3. Functions for manipulating files

1) On and off

  • fopen: Open a file, return a pointer to the file if successful, return a null pointer if it failsNULL
    • Function prototype:FILE* fopen(const char *path,const char *mode)
      • path: file path
      • mode: The opened mode
        mode is mainly composed of the following 6 characters:
        • r: readable (the file location pointer is at the head of the file, the file must exist)
        • w: writable (the file location pointer is at the head of the file, if the file exists, the content will be cleared, and if it does not exist, it will be created)
        • a: Append to write (the file position pointer is at the end of the file, the file must exist)
        • b: open in binary mode
        • +: readable and writable
        • t: text mode (default, can be omitted)
      • Common patterns are listed below:
        options illustrate
        r Read-only opens a text file, allowing only data to be read
        w Write-only Opens a text file, allowing only data to be written
        a Append write opens a text file and writes data at the end of the file
        rb Open a file in binary mode, allowing only data to be read
        wb Open a file in binary mode, allowing only data to be written
  • fclose: close a file, return 0 if successful, and return non-zero if failed.
    Usually, the file operation is as follows:
#include "stdio.h"
#include "stdlib.h"

FILE *fp = fopen("文件名", "打开模式");
if (fp == NULL) {
    
    
        printf("文件打开失败!");
        exit(1);
    }
    
/* 要执行的文件操作 */

fclose(fp);

2) File reading and writing

End of file:EOF
The function of file writing needs to open the file in write or read-write mode, and the function of file reading needs to open the file in read or read mode. After the read or write operation, the position pointer will move backward to the end of the read or write position

  • fgetc: read a character from a file
    • Function prototype:int fgetc(FILE *file);
      • file: pointer to the target file
    • Return value: Return the ASCII code of int type, and the position pointer moves backward by one byte
    • Instructions:fgetc(文件指针);
  • fputc: write a character to a file
    • Function prototype:int fputc(int c, FILE *file);
      • c: character to be written (char or int type ASCII code)
      • file: pointer to the target file
    • Return value: return the written character successfully, and move the position pointer backward by one byte; fail returnEOF
    • Instructions:fputc('a', 文件指针);
  • fgets: read a string from a file into a character array
    • Function prototype:char* fgets(char *Buffer, int MaxCount, FILE *file );
      • Buffer: pointer to character array
      • MaxCount: the maximum number of characters to read
      • file: pointer to the target file
    • illustrate:
      • MaxCount is a positive integer, indicating that the string read from the file does not exceed MaxCount-1 characters. Add the end-of-string flag after the last character read \0.
      • Before reading MaxCount-1 characters, if a newline character or EOF is encountered, the reading ends.
    • Return value: the first address of the character array
    • Instructions:fgets(数组首地址, 字符串最大长度, 文件指针);
  • fputs: write a string to a file,does not contain '\0'
    • Function prototype:int fputs(const char *str, FILE *file);
      • str: pointer to character array (string) to write
      • file: pointer to the target file
    • Return value: success returns a non-negative integer; failure returns EOF (a symbolic constant whose value is -1)
    • Instructions:fputs(字符串, 文件指针);
  • fread: Read a set of fixed-size data from a file into memory space
    • Function prototype:size_t fread(void *Buffer, size_t size, size_t count, FILE *file);
      • Buffer: the first address of the memory space (a memory space pointer used to store data)
      • size: the size of the data block
      • count: the number of data blocks
      • file: pointer to the target file
    • Return value: Returns the number of objects successfully read (if an error occurs or the end of the file is reached, it may be less than count)
    • Instructions:fread(内存空间地址, 数据块大小, 数据块数量, 文件指针);
  • fwrite: Write a set of fixed-size data to a file
    • Function prototype:size_t fwrite(const void *Buffer, size_t size, size_t count, FILE *file);
      • Buffer: the first address of the data to be stored
      • size: the size of the data block
      • count: the number of data blocks
      • file: pointer to the target file
    • Return value: returns the number of successfully written objects (if an error occurs or the end of the file is reached, it may be less than count)
    • Instructions:fwrite(数据地址, 数据块大小, 数据块数量, 文件指针);
  • fscanf: Get the data in the specified format from the file, similar to scanf, the input object is replaced by a normal file
    • Function prototype:int fscanf(FILE *file, const char *str, [arg...]);
      • file: pointer to the target file
      • str: format string
      • [arg…]: One or more addresses to receive data from
    • Description: fscanf encounteredspaceandnew lineend
    • Return value: Returns the number of parameters read in successfully, returns in failureEOF
    • Instructions:fscanf(文件指针, 格式化字符串, 目标地址);
  • fprintf: format the output data to a file, similar to printf, the output object is replaced with a normal file
    • Function prototype:int fprint(FILE *file, const char *str, [arg...]);
      • file: pointer to the target file
      • str: format string
      • [arg...]: one or more data
    • Description: fprintf will convert and format the data according to the parameter str string, and then output the result to the file specified by the parameter file until the end of the string ( ) appears \0.
    • Return value: successfully returns the number of output data, fails to returnEOF
    • Instructions:fprintf(文件指针, 格式化字符串, 目标数据);

3) File location

  • rewind: move the position pointer of the file to the head of the file
    • Function prototype:void rewind(FILE *file);
      • file: pointer to the target file
    • Instructions:rewind(文件指针);
  • fseek: Move the position pointer of the file from the specified starting point to a certain position
    • Function prototype:int fseek(FILE *file, long offset, int start);
      • file: pointer to the target file
      • offset: offset, how many bytes to move from the starting point, must be long data
      • start: starting point, specifying three starting points: the beginning of the file, the current position, and the end of the file
        starting point identifier digital representation
        file header SEEK_SET 0
        current location SEEK_CUR 1
        end of file SEEK_END 2
    • Instructions:fseek(文件指针, 偏移量, 起始点);

4) File detection

  • feof: Determine whether the file position pointer is at the end of the file

    • Function prototype:int feof(FILE *file);
      • file: pointer to the target file
    • Return value: Return non-0 when the file pointer is at the end position, otherwise return 0
  • ferror: check whether there is an error in the file when reading and writing with various input and output functions

    • Function prototype:int ferror(FILE *file);
      • file: pointer to the target file
    • Return value: return 0 if there is no error, return non-zero if there is an error
  • clearerr: Clear the error flag and end-of-file flag so that they are 0

    • Function prototype:void clearerr(FILE *file);
      • file: pointer to the target file

5) Example of file operation

#include "stdio.h"
#include "stdlib.h"

struct Student {
    
    
    char name[20];
    int age;
    float score;
};

int main() {
    
    
    FILE *fp = fopen("test.txt", "w+"); // 以读写模式打开一个文件
    if (fp == NULL) {
    
    
        printf("文件打开失败!");
        exit(1);
    }
    fputc('a', fp); // 向文件写入一个字符'a'
    rewind(fp); // 将文件位置指针放到文件头部,因为我们刚刚向文件写入了一个字符'a',所以现在文件位置指针指向的文件尾部
    char ch = (char)fgetc(fp); // 从文件读取一个字符,现在文件中只有一个'a',读取的字符就是'a'
    printf("%c\n",ch);
    printf("结束位置:%d\n", feof(fp)); // 看看位置指针是不是在结束位置
    fseek(fp,1L,0); // 将文件位置指针手动置于字符'a'后面,读取时也会把指针后移,但是写入的时候失败了,原因暂时未找到!
    fputs("this is fputs test", fp); // 向文件中写入字符串,现在文件中的内容应该是"athis is fputs test"
    printf("写入出错:%d\n",ferror(fp)); // 查看写入是否出错
    rewind(fp); // 位置指针放回文件头部
    char string[255]; // 定义一个字符数组用来存放字符串
    fgets(string, 255, fp); // 读取文件中的字符串到字符数组string中,遇到换行或文件末尾就结束
    printf("%s\n",string); // 输出:athis is fputs test
    rewind(fp); // 位置指针放回文件头部
    fprintf(fp,"%s %d %f","test", 1, 0.6f); // 现在文件内容是"test 1 0.600000test",因为现在写入的把前面的"athis is fputs "覆盖了
    rewind(fp);
    char str[255];
    int a;
    float b;
    fscanf(fp,"%s %d %f",str,&a,&b);
    printf("str的值:%s\na的值:%d\nb的值:%f",str,a,b);
    /*
    str的值:test
    a的值:1
    b的值:0.600000
     */
    fclose(fp);

    struct Student boys[3]; // 定义一个结构体数组
    struct Student boy2[2];
    struct Student *pb; // 定义一个结构体指针
    pb = boys; // 指向结构体中第一个成员(数组首地址)
    FILE *fp1 = fopen("test1.txt", "wb+"); // 以二进制读写模式打开一个文件
    if (fp1 == NULL) {
    
    
        printf("文件打开失败!");
        exit(1);
    }
    for (int i=0;i<3;i++){
    
    
        scanf("%s %d %f",pb->name,&pb->age,&pb->score); // 这里循环输入学生的信息
        pb++; // 指针向后移动,指向下一个boys数组的成员
    }
    long size = sizeof(struct Student); // 获取结构的大小
    fwrite(boys, size,3,fp1); // 向文件中写入3个Student结构
    rewind(fp1);
    fseek(fp1,size,SEEK_SET); // 位置指针移动到第二个学生的地址
    fread(boy2,size,2,fp1);  // 读取2个Student大小的数据
    for (int i=0; i < 2;i++) {
    
    
        printf("%s %d %f\n",boy2[i].name,boy2[i].age,boy2[i].score);
    }
    fclose(fp1); // 关闭文件
    return 0;
}

Guess you like

Origin blog.csdn.net/m0_56963884/article/details/128097655