Audio and video learning C language introduction

Posted by MissiCoola on Sat, 22 Jan 2022 22:41:10 +0100

preface

Now it is more and more difficult for Android junior and intermediate development engineers to find a satisfactory job. Of course, those with strength do not worry about a good job. If you happen to be a junior and intermediate engineer who wants to advance the direction of audio and video or is interested in NDK technology, you must be right to pay attention to me. With the advent of 5G era, I believe that engineers in the direction of audio and video will be more and more popular. If you want to learn audio and video technology, you must first have the basis of C/C + + language. Let's learn the basis of C language first.

ps: the audio and video direction plans to write a series of articles (the preliminary plan is based on C/C + + language, JNI, Makefile/Cmake, using FFmpeg to open voice video player, RTMP live broadcast, OpenCV face / license plate recognition, OpenGL video processing, video special effects, WebRTC audio and video call and other technical chapters). I will also continue to update this series. I didn't intend to write the basic articles of C/C + +. After reading my articles, I know that I wrote almost a series of articles. If I lack arms and legs, it doesn't look so clear. Therefore, I wrote the basic articles of C/C + + with reference to the ones on the Internet. Because there are too many good introductory materials on the Internet, this article should be used as a review reference. Those who have this foundation can turn the page directly 😂.

Don't talk so much nonsense. Let's learn the technology of audio and video together, so that we can't extricate ourselves from our study 😁.

C introduction

C language is a general high-level language, which was originally designed by Dennis Ritchie to develop UNIX operating system in Bell laboratory. C language was first implemented on DEC PDP-11 computer in 1972.

In 1978, Brian Kernighan and Dennis Ritchie produced the first publicly available description of C, now known as the K & R standard.

UNIX operating system, C compiler, and almost all UNIX applications are written in C language. For various reasons, C language has become a widely used professional language.

  • Easy to learn.
  • Structured language.
  • It produces efficient programs.
  • It can handle the underlying activities.
  • It can be compiled on a variety of computer platforms.

Environment settings

This only explains how to use the C language for development on the MAC. If the environment needs GCC for compilation, you can download and install the Xcode tool. Once Xcode is installed, you can use the GNU compiler. You can use Xcode or CLion as development tools. It depends on your personal preferences. I use the CLion tool here. You can find that the CLion page style, including shortcut keys, is the same as that of Android studio. It's extremely easy to get started.

Introduction to C language

I wonder what is the first line of code when you are learning a new development language? More than 90% should print "HelloWorld". Let's take printing "HelloWorld" as an example to officially enter the learning of C language.

1. Program structure

Let's take a look at the simplest C program. First, print a "HelloWorld". The code is as follows:

#include <stdio.h>
/**
 * C Language entry program
 * @return
 */
int main() {//Main function, the program starts from here
    printf("C Language introduction first line of code Hello World! \n");
    return 0;
} 

You can see that the entry function of C language is similar to that of Java. They are all entries defined in main. Next, let's explain the meaning of the above program:

  1. The first line of the program #include < stdio h> Is a preprocessor instruction that tells the C compiler to include stdio before actual compilation H file.
  2. The next line /.... / will be ignored by the compiler, where the comments of the program are placed. They are called program annotations.
  3. The next line, int main(), is the main function from which the program starts.
  4. The next line printf(...) is another available function in C, which will display the message "the first line of code for getting started with C language Hello World!" on the screen.
  5. Next line return 0; Terminate the main() function and return a value of 0.

Of course, you can execute it by command, as follows:

1. use gcc xxx.c
2. ./a.out 

Directly use the above two steps to execute C code.

2. Basic grammar

In the last section, we learned what a simple small application consists of, which will help us understand other basic building blocks of C language.

c program consists of various tokens, which can be keywords, identifiers, constants, string character values, or a symbol.

Let's take a look at the keywords in C. these keywords cannot be used as constant names, variable names or other identifier names (similar to Java).

keywordexplain
autoDeclare automatic variables
breakJump out of current loop
caseSwitch statement branch
charDeclare the return value type of a character variable or function
constDeclare only readable variables
continueEnd the current cycle and start the next cycle
defaultOther branches in switch statements
doThe body of a loop statement
doubleDeclare a double progress floating-point variable or function return value type
elseConditional statement negative branch
enumDeclare enumeration type
externDeclare that variables or functions are defined in other documents or elsewhere in this document
floatDeclare the return value type of a floating-point variable or function
forA circular statement
gotoUnconditional jump statement
ifConditional statement
intDeclare an integer variable or function
longDeclare the return value type of a long integer variable or function
registerDeclare register variables
returnSubroutine return statement
shortDeclare a short integer variable or function
signedDeclare a variable or function of signed type
sizeofCalculate the data type or variable length (i.e. the number of bytes)
staticDeclare static variables
structDeclare structure type
switchFor switch statements
typedefUsed to alias data types
unsignedDeclare an unsigned variable or function
unionDeclare common body type
voidThe declared function has no return value or parameter tree, and the declared function has no type pointer
volatileDescription variables can be changed implicitly during program execution
whileLoop condition of loop statement

3. Data type

In C language, data type refers to a wide range of systems used to declare different types of variables or functions. The type of variable determines the space occupied by variable storage and how to interpret the stored bit pattern.

The types in C can be divided into the following types:

typeexplain
Basic typeThey are arithmetic types, including two types: integer type and floating point type.
Enumeration typeThey are also arithmetic types and are used to define variables that can only be given a certain discrete integer value in the program.
void typeThe type specifier void table name has no available values
Derived typeThey include pointer type, array type, structure type, common body type and function type.

Integer type

The following table lists details about the storage size and value range of standard integer types

type32 bit64 bitValue range
char11-128 to 127 or 0 to 255
unsigned char110 to 255
int44-32768 to 32767 or - 2147483648 to 2147483647
unsigned int440 to 65535 or 0 to 4294967295
short22-32768 to 32767
unsigned short220 to 65535
long48-2147483648 to 2147483647
unsigned long480 to 4294967295

Note: the size of various types of storage is related to the number of bits in the system, but the current general system is mainly 64.

Floating point type

typeNumber of bitsSignificant numberValue range
float46~71.2E-38 to 3.4E+38
double815~162.3E-308 to 1.7E+308
long double1618~193.4E-4932 to 1.1E+4932

Their byte, precision and value range can be realized through code printing, as follows:

void main() {
		/**
     * Integer type
     */

    printf("\n\n Integer type \n");

    //char 1 byte
    printf("char Storage size: %lu \n", sizeof(char));
    printf("unsinged char Storage size: %lu \n", sizeof(unsigned char));

    //short 2 bytes
    printf("short Storage size: %lu \n", sizeof(short));
    printf("unsinged short Storage size: %lu \n", sizeof(unsigned short));

    //int 4 bytes
    printf("int Storage size: %lu \n", sizeof(int));
    printf("unsinged int Storage size: %lu \n", sizeof(unsigned int));


    //long 4/8 bytes
    printf("long Storage size: %lu \n", sizeof(long));
    printf("unsinged long Storage size: %lu \n", sizeof(unsigned long));

		/**
     * Floating point type
     */

    printf("\n\n Floating point type \n");
    //float 4 bytes, precision 6 decimal places
    printf("float Maximum bytes stored:%lu \n", sizeof(float));
    printf("float Minimum:%e \n", FLT_MIN);
    printf("float Maximum:%e \n", FLT_MAX);
    printf("float Precision value:%d \n", FLT_DIG);

    //double 8 bytes
    printf("double Maximum bytes stored:%d \n", sizeof(double));
    printf("double Minimum:%e \n", DBL_MIN);
    printf("double Maximum:%e \n", DBL_MAX);
    printf("double Precision value:%d \n", DBL_DIG);

    //long double 16 bytes
    printf("long double Maximum bytes stored:%lu byte \n", sizeof(long double));
    printf("long double Minimum:%lg \n", LDBL_MIN);
    printf("long double Maximum:%lg \n", LDBL_MAX);
    printf("long double Precision value:%d \n", LDBL_DIG);

} 

You can use the sizeof keyword to get the memory occupied by the data type. As can be seen from the above code, there are many unknown scanf() format controllers in printing. I have summarized a table, which can be referred to below:

Format controllerexplain
%cRead a single character
%hd,%d,%ldRead a decimal integer and assign it to short, int and long types respectively
%ho,%o,%loRead an octal integer (with or without prefix) and assign it to types short, int and long respectively
%hx,%x,%lxRead a hexadecimal integer (with or without prefix) and assign it to types short, int and long respectively
%hu,%u,%luRead an unsigned integer and assign it to unsigned short, unsigned int and unsigned long types respectively
%f,%lfRead a decimal number in decimal form and assign it to float and double types respectively
%e,%leRead a decimal in exponential form and assign it to float and double types respectively
%g,%lgYou can read either a decimal decimal or an exponential decimal and assign them to float and double types respectively
%sRead a string (ending with a blank character)

4. Variables

A variable is simply the name of the storage area that the program can operate on. Each variable in C has a specific type. The type determines the size and layout of variable storage. The values within this range can be stored in memory, and operators can be applied to variables.

The name of a variable can consist of letters, numbers, and underscore characters. It must start with a letter or underscore. Uppercase and lowercase letters are different because C is case sensitive.

Variable definition in C

Variable definition is to tell the compiler where to create variable storage and how to create variable storage. The variable definition specifies a data type and contains a list of one or more variables of that type, as shown below:

type list; 

Here, type must be a valid C data type, which can be char and w_char, int, float, double or any user-defined object. The list can be composed of one or more identifier names separated by commas. Several valid statements are listed below:

int a,b,c;
char c1,c2,c3;
float f,f1,f2;
double d1,d2,d3; 

This is actually similar to Java declaration variables, so it is no longer explained separately.

Variable declaration in c

The variable declaration guarantees the compiler that the variable exists with the specified type and name, so that the compiler can continue to compile further without knowing the full details of the variable. Variable declaration only has its meaning at compile time. The compiler needs actual variable declaration when connecting programs.

There are two cases of variable declaration:

  • 1. One is to establish storage space. For example, int a has already established storage space at the time of declaration.
  • 2. The other is to declare the variable name without defining it by using the extern keyword. For example: extern int a, where variable a can be defined in other files.
  • Unless there is an extern keyword, it is the definition of variables.
extern int i;//Declaration, not definition
int a;//Declaration is also a definition 

example

#include <stdio.h>
//Variables defined outside the function 
//If a variable defined in another source file needs to be referenced in one source file, we only need to add the declaration of extern keyword to the variable in the referenced file
int x;
int y;

int sum() {
    //The variable x is declared inside the function, and Y is the external variable
    x = 10;
    y = 15;
    return x + y;
}

//Entry function
void main() {
    //Print variable addition
    int result;
    result = sum();
    printf("x + y = %d",result);
} 

Output:

x + y = 25 

5. Constant

Constants are fixed values and do not change during program execution. These fixed values are also called literal values.

Constants can be any basic data type, such as integer constants, floating-point constants, character constants, or string literals, as well as enumeration constants.

Constants are like regular variables, but their values cannot be modified after definition.

To declare a constant in Java, you need to define the final keyword in the data type, but there is no final keyword in c. let's see how to define it, as shown below:

integer constant

Integer constants can be decimal, octal, or hexadecimal constants. Prefix specifies the base: 0X or 0X indicates hexadecimal, 0 indicates octal, and without prefix, it indicates decimal by default.

Integer constants can also have a suffix. The suffix is a combination of U and L. U represents an unsigned integer and l represents a long integer. Suffixes can be uppercase or lowercase, in any order of U and L.

212         /* lawful */
215u        /* lawful */
0xFeeL      /* lawful */
078         /* Illegal: 8 is not an octal number */
032UU       /* Illegal: suffix cannot be repeated */ 

Floating-Point Literals

Floating point constants are composed of integer part, decimal point, decimal part and exponential part. You can express floating-point constants in decimal or exponential form.

When expressed in decimal form, it must include integer part, decimal part, or both. When expressed in exponential form, it must include decimal point, exponential, or both. The signed exponent is introduced by E or E.

3.14159       /* lawful */
314159E-5L    /* lawful */
510E          /* Illegal: incomplete index */
210f          /* Illegal: no decimals or exponents */
.e55          /* Illegal: missing integer or fraction */ 

Define constants

In C, there are two simple ways to define constants:

  1. Use #define preprocessor.
  2. Use the const keyword.

The following is the form of defining constants using #define preprocessor:

#define identifier value 

example:

#define name 10L
#define age 27U
void main() {
    int  person;
    person = name + age;
    printf("values :%d",person);

} 

const keyword

You can declare constants of the specified type using const prefix, as follows:

const type variable = value; 

example:

void main() {
    const int LEGTH = 10;
    const int WIDTH = 5;
    const char NEWLINE = '\n';
    int area;
    area = LEGTH * WIDTH;
    printf("value of area: %d", area);
} 

6. Storage class

Storage classes define the scope (visibility) and life cycle of variables / functions in C programs. These specifiers are placed before the type they modify. The storage classes available in the C program are listed below:

  • auto
  • register
  • static
  • extern

auto storage class

auto storage class is the default storage class for all local variables.

int month;
auto int month; 

Two classes with the same storage are defined above. Auto can only be used in functions, that is, auto can only modify local variables.

register storage class

The register storage class is used to define local variables stored in registers rather than RAM. This means that the maximum size of the variable is equal to the size of the register (usually a word), and the unary '&' operator cannot be applied to it (because it has no memory location).

register int miles; 

Registers are only used for variables that require fast access, such as counters. It should also be noted that defining register does not mean that variables will be stored in registers, it means that variables may be stored in registers, depending on hardware and implementation limitations.

static storage class

The static storage class instructs the compiler to maintain the existence of local variables throughout the life cycle of the program without creating and destroying them every time it enters and leaves the scope. Therefore, using static to modify local variables can maintain the value of local variables between function calls. The static modifier can also be applied to global variables. When static modifies a global variable, it limits the scope of the variable to the file in which it is declared.

A globally declared static variable or method can be called by any function or method as long as these methods appear in the same file as the static variable or method.

example:

//Function declaration
void func1(void);

static int count = 10; //Global variable - static default
void main() {
    while (count--) {
        func1();
    }
}

void func1(void) {
//   'thingy 'is a local variable of' func1 '- initialized only once
// *The 'thingy' value of 'func1' will not be reset every time the function is called. 
    static int thingy = 5;
    thingy++;
    printf("thingy by %d, count by %d \n", thingy, count);
} 

Output:

thingy For 6, count For 9 
thingy For 7, count For 8 
thingy For 8, count For 7 
thingy For 9, count For 6 
thingy For 10, count For 5 
thingy For 11, count For 4 
thingy For 12, count For 3 
thingy For 13, count For 2 
thingy For 14, count Is 1 
thingy For 15, count Is 0 

In the instance, count can be used in the function as a global variable. thingy will not be reset every time it is called after it is decorated locally with static.

extern storage class

The extern storage class is used to provide a reference to a global variable, which is visible to all program files. When you use extern, for variables that cannot be initialized, the variable name will point to a previously defined storage location.

When you have multiple files and define a global variable or function that can be used in other files, you can use extern in other files to get a reference to the defined variable or function. It can be understood that extern is used to declare a global variable or function in another file.

The extern modifier is usually used when two or more files share the same global variable or function, as follows:

First file ndk_day1.c

#include <stdio.h> //stdio.h is a header file (standard input / output header file), #include is a preprocessing command used to import header files.
#include "support.h" / / import your own header file
int main() {
    int sum = add(2, 5);
    printf("extern use :%d", sum);
} 

Declare support H header file

//
// Created by yangkun on December 13, 2019
//

#ifndef NDK_SAMPLE_SUPPORT_H
#define NDK_SAMPLE_SUPPORT_H

#endif //NDK_SAMPLE_SUPPORT_H

extern int add(int num1,int num2); 

Implementation of header file support c

int add(int num1,int num2){
    return num1 * num2;
} 

Output:

extern use :10 

7. Operator

An operator is a symbol that tells the compiler to perform a specific mathematical or logical operation. C language has built-in rich operators and provides the following types of operators:

  • Arithmetic operator
  • Relational operator
  • Logical operator
  • Bitwise Operators
  • Assignment Operators
  • Miscellaneous operator

Arithmetic operator

The following table shows all arithmetic operators supported by the C language. Assuming that the value of variable A is 10 and the value of variable B is 20, then:

operatordescribeexample
+Add the two operandsA + B will get 30
-Subtracts the second operand from the first operandA - B will get - 10
*Multiply two operandsA * B will get 200
/Numerator divided by denominatorB / A will get 2
%Modulo operator, remainder after divisionB% a will get 0
++Self increasing operator, the integer value is increased by 1A + + will get 11
Self subtraction operator, the integer value is reduced by 1A -- will get 9

example:

void main(){
    int a = 21;
    int b = 10;
    int c;

    c = a + b;
    printf("a + b = %d \n", c);

    c = a - b;
    printf("a - b = %d \n", c);

    c = a * b;
    printf("a * b = %d \n", c);

    c = a / b;
    printf("a / b = %d \n", c);

    c = a % b;
    printf("a % b = %d \n", c);

    c = ++a;
    printf("++a = %d , %d \n", c, a);

    c = b++;
    printf("b++ = %d , %d \n", c, b);

    c = b--;
    printf("b-- = %d \n", c);
} 

Output:

a + b = 31 
a - b = 11 
a * b = 210 
a / b = 2 
a b = 1 
++a = 22 , 22 
b++ = 10 , 11 
b-- = 11 

Relational operator

The following table shows all the relational operators supported by the C language. Assuming that the value of variable A is 10 and the value of variable B is 20, then:

operatordescribeexample
==Checks whether the values of the two operands are equal. If they are equal, the condition is true.(A == B) is false.
!=Checks whether the values of the two operands are equal. If they are not equal, the condition is true.(a! = b) is true.
>Check whether the value of the left operand is greater than the value of the right operand. If so, the condition is true.(a > b) is false.
<Check whether the value of the left operand is less than the value of the right operand. If so, the condition is true.(a < b) is true.
>=Check whether the value of the left operand is greater than or equal to the value of the right operand. If so, the condition is true.(a > = b) is false.
<=Check whether the value of the left operand is less than or equal to the value of the right operand. If so, the condition is true.(a < = b) is true.

Logical operator

The following table shows all the relational logic operators supported by the C language. Assuming that the value of variable A is 1 and the value of variable B is 0, then:

operatordescribeexample
&&They are called logical and operators. If both operands are non-zero, the condition is true.(A & & B) is false.
!It is called a logical non operator. Used to reverse the logical state of an operand. If the condition is true, the logical non operator makes it false.! (A & & B) is true.
void main(){
   int a1 = 5;
    int b1 = 5;
    int c1;
    //If both operands are non-zero, the condition is true.
    if (a1 && b1) {
        printf("a1 && b1  %d \n", true);
    } else {
        printf("a1 && b1  %d \n", false);
    }
    //If either of the two operands is non-zero, the condition is true.
    if (a1 || b1) {
        printf("a1 || b1  %d \n", true);
    } else {
        printf("a1 || b1  %d \n", false);
    }

    //Change the value of A1 and B1
    a1 = 0;
    b1 = 10;

    //If both operands are non-zero, the condition is true.
    if (a1 && b1) {
        printf("a1 && b1  %d \n", true);
    } else {
        printf("a1 && b1  %d \n", false);
    }

    if (!(a1 && b1)) {
        printf("!(a1 && b1)  %d \n", true);
    } else {
        printf("a1 || b1  %d \n", false);
    }

} 

Output:

a1 && b1  1 
a1 || b1  1 
a1 && b1  0 
!(a1 && b1)  1 

Bitwise Operators

| p | q | p & q | p | q | p ^ q |
| — | — | — | — | — |
| 0 | 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 1 | 1 |
| 1 | 1 | 1 | 1 | 0 |
| 1 | 0 | 0 | 1 | 1 |

void main(){
   //Bitwise operators & |~
    int wA = 60; //0011 1100
    int wB = 13; //0000 1101
    int wC = 10;

    //It's true if it's all true
    printf("wA & wB=?%d\n", wA & wB);

    //If one of them is true, it is true 0011 1101
    printf("wA | wB=?%d\n", wA | wB);

    //If one is true, it is true, and if two are true, it is false 00110001
    printf("wA ^ wB=?%d\n", wA ^ wB);

    printf("~wB=?%d\n", ~wB);


    //Binary shift left operator * 4 = 40
    printf("wC<<2=?%d\n", wC << 2);

    //Binary shift right operator right / 4
    printf("wC>>2=?%d\n", wC >> 2);
} 

Output:

wA & wB=?12
wA | wB=?61
wA ^ wB=?49
~wB=?-14
wC<<2=?40
wC>>2=?2 

The following table shows the bitwise operators supported by the C language. Assuming that the value of variable A is 60 and the value of variable B is 13, then:

operatordescribeexample
&And operation by bit, and operation by binary bit. Operation rules: 0 & 0 = 0; 0&1=0; 1&0=0; 1&1=1;(A & B) will get 12, which is 0000 1100
Bitwise OR operator, or operation in binary bits. Operation rule: 0|0 = 0; 0|1=1; 1|0=1; 1|1=1;
^XOR operator, which performs "XOR" operation according to binary bits. Operation rule: 0 ^ 0 = 0; 0^1=1; 1^0=1; 1^1=0;(A ^ B) will get 49, i.e. 0011 0001
~Negation operator, which performs "Negation" operation according to binary bits. Operation rule: ~ 1 = 0~ 0=1;(~ A) will get - 61, i.e. 1100 0011, the complement form of A signed binary number.
<<Binary shift left operator. Shift all binary bits of an operand to the left by several bits (the binary bits on the left are discarded and 0 is filled on the right).A < < 2 will get 240, i.e. 1111 0000
>>Binary shift right operator. All binary bits of a number are shifted to the right by several bits, positive numbers are supplemented by 0 to the left, negative numbers are supplemented by 1 to the left, and the right is discarded.A > > 2 will get 15, which is 0000 1111

Assignment Operators

The following table lists the assignment operators supported by C language:

operatordescribeexample
=A simple assignment operator assigns the value of the right operand to the left operandC = A + B will assign the value of A + B to C
+=The addition and assignment operator assigns the result of the right operand plus the left operand to the left operandC += A is equivalent to C = C + A
-=The minus and assignment operator assigns the result of subtracting the right operand from the left operand to the left operandC -= A is equivalent to C = C - A
*=The multiply and assign operator assigns the result of multiplying the right operand by the left operand to the left operandC *= A is equivalent to C = C * A
/=The division and assignment operator assigns the result of dividing the left operand by the right operand to the left operandC /= A is equivalent to C = C / A
%=The modulo and assignment operator evaluates the modulo of the two operands and assigns it to the left operandC% = a is equivalent to C = C% a
<<=Shift left and assignment operatorC < < 2 is equivalent to C = C < < 2
>>=Shift right and assignment operatorC > > = 2 is equivalent to C = C > > 2
&=Bitwise AND and assignment operatorC & = 2 is equivalent to C = C & 2
^=Bitwise exclusive or and assignment operatorC ^= 2 is equivalent to C = C ^ 2
=Bitwise OR and assignment operator

example:

void main(){
int wAA = 21;
    int wBB;

    wBB = wAA;
    printf("= %d\n", wBB);

    wBB += wAA;
    printf("+= %d\n", wBB);

    wBB -= wAA;
    printf("-= %d\n", wBB);

    wBB *= wAA;
    printf("*= %d\n", wBB);

    wBB /= wAA;
    printf("/= %d\n", wBB);

    wBB %= wAA;
    printf("%= %d\n", wBB);

    wBB <<= wAA;
    printf("<<= %d\n", wBB);

    wBB <<= wAA;
    printf(">>= %d\n", wBB);

    wBB &= wAA;
    printf("&= %d\n", wBB);

    wBB ^= wAA;
    printf("^= %d\n", wBB);

    wBB |= wAA;
    printf("|= %d\n", wBB);
} 

Output:

= 21
+= 42
-= 21
*= 441
/= 21
= 0
<<= 0
>>= 0
&= 0
^= 21
|= 21 

Miscellaneous operators sizeof, &, ternary

The following table lists some other important operators supported by C language, including sizeof and?:.

operatordescribeexample
sizeof()Returns the size of the variable.sizeof(a) returns 4, where a is an integer.
&Returns the address of the variable.&a; The actual address of the variable will be given.
*Point to a variable.*a; Points to a variable.
? :Conditional expressionIf the condition is true? Then the value is X; otherwise, the value is Y

example:

void main(){
  	int zxA = 4;
    short zxB;
    double zxC;
    int *ptr;

    //sizeOf operator instance, lu 32-bit unsigned integer
    printf("zxA sizeOf = %lu \n", sizeof(zxA));
    printf("zxB sizeOf = %lu \n", sizeof(zxB));
    printf("zxC sizeOf = %lu \n", sizeof(zxC));

    //&And * operator instances
    ptr = &zxA; //Copy the address value of zxA to the ptr pointer
    printf("zxA The value of is:%d \n", zxA);
    printf("*ptr The value of is:%d \n", *ptr);
  
  	//Ternary operator 
    zxA = 10;
    zxB = (zxA == 1) ? 20 : 30;
    printf("zxb The value of is:%d \n", zxB);

    zxB = (zxA == 10) ? 20 : 30;
    printf("zxb The value of is:%d \n", zxB);
} 

Output:

zxA sizeOf = 4 
zxB sizeOf = 2 
zxC sizeOf = 8 
zxA The value of is: 4 
*ptr The value of is: 4 
zxb The value of is: 30 
zxb The value of is: 20 

8. Judgment

C language assumes any non-zero and non null value as true and zero or null as false.

C language provides the following types of judgment statements. Click the link to view the details of each statement.

sentencedescribe
if statementAn if statement consists of a Boolean expression followed by one or more statements.
if... else statementAn if statement can be followed by an optional else statement, which is executed when the Boolean expression is false.
Nested if statementYou can use another if or else if statement within one if or else if statement.
switch statementA switch statement allows you to test when a variable is equal to multiple values.
Nested switch statementsYou can use another switch statement within one switch statement.

?: operator

Just like Java

void main(){
 		int pdNumber;
    printf("Enter a number:");
    scanf("%d", &pdNumber);
    (pdNumber % 2 == 0) ? printf("even numbers") : printf("base");
} 

9. Circulation

C language provides the following loop types. Click the link to view the details of each type.

Cycle typedescribe
while loopWhen the given condition is true, repeat the statement or statement group. It tests the condition before executing the loop body.
for loopExecute a statement sequence multiple times to simplify the code for managing loop variables.
do... while loopIt is similar to the while statement except that it tests the condition at the end of the loop body.
Nested loopYou can use one or more loops within a while, for, or do... While loop.

Loop control statement

Loop control statements change the execution order of your code. You can jump the code through it.

C provides the following loop control statements. Click the link to view the details of each statement.

Control statementdescribe
break statementWhen the loop or switch statement is terminated, the program flow will continue to execute the next statement following the loop or switch.
continue statementTell a loop body to stop this loop iteration immediately and restart the next loop iteration.
goto statementTransfers control to the marked statement. However, it is not recommended to use goto statements in programs.

You can refer to Java for the use method. The following is an example of a loop:

void main(){
      //limit
    for (int i = 0; i < 6; i++) {
        printf("Limit cycle,%d \n",i);
    }
    //Infinite loop
    for (;;) {
        printf("The loop will continue!\n");
    }
} 

10. Function

Function definition

The general form of function definition in C language is as follows:

return_type function_name( parameter list ) {
   body of the function
} 

In C language, a function consists of a function header and a function body. All components of a function are listed below:

  • **Return type: * * a function can return a value. return_type is the data type of the value returned by the function. Some functions perform the required operation without returning a value. In this case, return_type is the keyword void.
  • **Function name: * * this is the actual name of the function. The function name and the parameter list together form the function signature.
  • **Parameters: * * parameters are like placeholders. When the function is called, you pass a value to the parameter, which is called the actual parameter. The parameter list includes the type, order and quantity of function parameters. Parameters are optional, that is, functions may not contain parameters.
  • **Function body: * * the function body contains a set of statements that define the function execution task.

example:

/* Function returns the larger of the two numbers */
int max(int num1, int num2) {
   /* Local variable declaration */
   int result;
 
   if (num1 > num2)
      result = num1;
   else
      result = num2;
 
   return result; 
} 

Function declaration

The function declaration tells the compiler the name of the function and how to call it. The actual body of a function can be defined separately.

The function declaration includes the following parts:

return_type function_name( parameter list ); 

For the function max() defined above, the following is the function declaration:

int max(int num1, int num2); 

In the function declaration, the name of the parameter is not important. Only the type of the parameter is required. Therefore, the following is also a valid declaration:

int max(int, int); 

When you define functions in a source file and call functions in another file, function declarations are required. In this case, you should declare the function at the top of the file that calls the function.

Call function

//Function declaration
int max(int num1, int num2);

/**
 *C function
 */
void main() {
    //Find the maximum value in the function
    printf("Find the maximum value in the function,%d \n",max(66,88));

}

int max(int num1, int num2) {
    return (num1 > num2) ? num1 : num2;
} 

Output:

Find the maximum value in the function, 88 

Function parameters

If a function wants to use parameters, it must declare variables that accept parameter values. These variables are called formal parameters of the function.

Formal parameters, like other local variables in a function, are created when entering the function and destroyed when exiting the function.

Call typedescribe
Value passing callThis method copies the actual value of the parameter to the formal parameter of the function. In this case, modifying the formal parameters in the function will not affect the actual parameters.
Reference callThrough the pointer transfer method, the formal parameter is a pointer to the address of the argument. When the pointing operation of the formal parameter is equivalent to the operation of the argument itself.

11. Scope rules

In any kind of programming, the scope is the area where the variables defined in the program exist, beyond which the variables cannot be accessed. There are three places in C language where variables can be declared:

  1. A local variable inside a function or block
  2. Global variables outside all functions
  3. In the function parameter definition of formal parameters

Let's look at what local variables, global variables, and formal parameters are.

local variable

Variables declared inside a function or block are called local variables. They can only be used by statements inside the function or the code block. Local variables are unknowable outside the function. The following is an example of using local variables. Here, all variables a, b, and c are local variables of the main() function.

void main(){
    //local variable
    int a, b;
    int c;
    //Initializing local variables
    a = 10;
    b = 20;
    c = a + b;
    //%d: Output signed integers in decimal form (positive numbers do not output symbols)
    printf("values of a = %d,b = %d and c = %d \n", a, b, c);
} 

Output:

values of a = 10,b = 20 and c = 30 

global variable

Global variables are defined outside the function, usually at the top of the program. Global variables are valid throughout the program life cycle, and can be accessed within any function.

Global variables can be accessed by any function. That is, global variables are available throughout the program after declaration. The following are examples of using global and local variables:

//Global variable declaration
int g;
void main(){
   int a, b;
    //Initializing local variables
    a = 10;
    b = 20;
   //Assignment of all variables
    g = a + c;
    printf("values of a = %d,bc = %d and g = %d \n", a, c, g);
} 

Output:

values of a = 10,bc = 30 and g = 40 

Formal parameters

The parameters and formal parameters of a function are regarded as local variables in the function. If they have the same name as global variables, they will be used preferentially. Here is an example:

int sumA(int a, int b) {
    printf("value of a in sum() = %d\n", a);
    printf("value of b in sum() = %d\n", b);
    return x + y;
}

void main(){
  int a, b,c;
    //Initializing local variables
    a = 10;
    b = 20;
  c = sumA(a, b);
  printf("value of c in main() = %d\n", c);
} 

Output:

value of a in main() = 30 

The difference between global variables and local variables

  • Global variables are stored in the global storage area of memory and occupy static storage units;
  • Local variables are stored in the stack, and storage units are dynamically allocated to variables only when the function is called.

Initializes default values for local and global variables

data typeInitialize defaults
int0
char'\0'
float0
double0
pointerNULL

12. Array

C language supports array data structure, which can store an ordered collection of elements of the same type with a fixed size. Array is used to store a series of data, but it is often regarded as a series of variables of the same type.

The declaration of array is not to declare individual variables, such as number0, number1,..., number99, but to declare an array variable, such as numbers, and then use numbers[0], numbers[1],..., numbers[99] to represent individual variables. Specific elements in the array can be accessed by index.

All arrays consist of contiguous memory locations. The lowest address corresponds to the first element and the highest address corresponds to the last element.

Declaration array

To declare an array in C, you need to specify the type and number of elements, as shown below:

type arrayName [ arraySize ]; 

This is called a one-dimensional array. arraySize must be an integer constant greater than zero, and type can be any valid C data type. For example, to declare an array balance with 10 elements of type double, the declaration statement is as follows:

double balance[10]; 

Initialize array

void main(){
  double balance[10] = {1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2.0}
} 

The number of values between braces {} cannot be greater than the number of elements specified in square brackets [] when we declared the array.

If you omit the size of the array, the size of the array is the number of elements at initialization. Therefore, if:

void main(){
  double balance[] = {1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2.0}
} 

You will create an array that is exactly the same as the array created in the previous instance. The following is an example of assigning a value to an element in an array:

balance[1] = 50.5; 

Accessing array elements

//Just like Java
double value = balance[1] 

example:

void main() {
    //Defines an array of integers with a length of 10
    int n[10];
    int i, j;

    //Initialize array elements
    for (i = 0; i < 10; i++) {
        n[i] = 2 * i;
    }

    //Data in output element
    for (int k = 0; k < 10; ++k) {
        printf("Element[%d] = %d \n", k, n[k]);
    }

    //The total size is divided by one of the sizes to get the array length
    printf("Integer array n Length of: %d \n", sizeof(n) / sizeof(n[0]));

    //Data in output element
    for (int k = 0; k < sizeof(n) / sizeof(n[0]); ++k) {
        printf("Element[%d] = %d \n", k, n[k]);
    }
} 

Output:

Element[0] = 0 
Element[1] = 2 
Element[2] = 4 
Element[3] = 6 
Element[4] = 8 
Element[5] = 10 
Element[6] = 12 
Element[7] = 14 
Element[8] = 16 
Element[9] = 18 
Integer array n Length of: 10 
Element[0] = 0 
Element[1] = 2 
Element[2] = 4 
Element[3] = 6 
Element[4] = 8 
Element[5] = 10 
Element[6] = 12 
Element[7] = 14 
Element[8] = 16 
Element[9] = 18 

Detailed explanation of array in C

In C, arrays are very important. We need to know more about arrays. Here are some important concepts related to arrays that C programmers must be aware of:

conceptdescribe
Multidimensional arrayC supports multidimensional arrays. The simplest form of multidimensional array is two-dimensional array.
Pass array to functionYou can pass a pointer to the array to the function by specifying an array name without an index.
Returns an array from a functionC allows an array to be returned from a function.
Pointer to arrayYou can generate a pointer to the first element in the array by specifying an array name without an index.

13. Enumeration

Enumeration is a basic data type in C language. It can make data more concise and easier to read.

The definition format of enumeration syntax is:

enum&emsp;Enumeration name&emsp;{Enumeration element 1,Enumeration element 2,......}; 

Next, let's take an example. For example, there are 7 days a week. If enumeration is not needed, we need to use #define to define an alias for each integer:

#define MON  1
#define TUE  2
#define WED  3
#define THU  4
#define FRI  5
#define SAT  6
#define SUN  7 

It seems that there is a large amount of code. Next, let's look at the way to use enumeration:

enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
}; 

Does this look more concise.

**Note: * * the default value of the first enumeration member is integer 0, and the value of subsequent enumeration members is added to the previous member by 1. In this example, we define the value of the first enumeration member as 1, the second as 2, and so on.

You can change the value of an enumeration element when defining an enumeration type:

enum season {spring, summer=3, autumn, winter}; 

Enumeration elements that do not have a specified value have a value of the previous element plus 1. In other words, the value of spring is 0, the value of summer is 3, the value of autumn is 4, and the value of winter is 5

Enumeration variable definition

We just declared the enumeration type. Next, let's see how to define the enumeration variable.

We can define enumeration variables in the following three ways

1. Define the enumeration type first, and then the enumeration variable

enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
};
enum DAY day; 

2. Define enumeration variables while defining enumeration types

enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
} day; 

3. Omit the enumeration name and directly define the enumeration variable

enum
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
} day; 

example:

void main() {
    //Traverse a week
    for (day = MON; day <= SUN; day++) {
        printf("week: %d \n", day);
    }

    enum color { red=1, green, blue ,black};

    enum  color favorite_color;

//     ask user to choose color
    printf("Please enter your favorite color: (1. red, 2. green, 3. blue): ");
    scanf("%d", &favorite_color);

//     Output results
    switch (favorite_color)
    {
        case red:
            printf("Your favorite color is red");
            break;
        case green:
            printf("Your favorite color is green");
            break;
        case blue:
            printf("Your favorite color is blue");
            break;
        case black:
            printf("Your favorite color is black");
            break;
        default:
            printf("You didn't choose the color you like");
    }


    //Converts an integer to an enumeration
    enum day
    {
        saturday,
        sunday,
        monday,
        tuesday,
        wednesday,
        thursday,
        friday
    } ;
    int a = 1;
    enum day weekend;
    weekend = (enum day)a;
    printf("weekend:%d \n",weekend);
} 

Output:

week: 1 
week: 2 
week: 3 
week: 4 
week: 5 
week: 6 
week: 7 
Please enter your favorite color: (1. red, 2. green, 3. blue): 1
 Your favorite color is red weekend:1 

14. Pointer

Learning the pointer of C language is simple and interesting. Through the pointer, the execution of some C programming tasks can be simplified, and some tasks, such as dynamic memory allocation, cannot be executed without the pointer. Therefore, to become an excellent C programmer, it is necessary to learn pointers.

As you know, each variable has a memory location. Each memory location defines an address that can be accessed using the hyphen (&) operator, which represents an address in memory. Take a look at the following ex amp le, which will output the defined variable address:

void main(){
    int var1;
    char var2[10];
    //%p: Output pointer address
    printf("var1 Address of variable:%p \n", &var1);
    printf("var2 Address of variable:%p \n", &var2);
} 

Output:

var1 Address of variable: 0 x7ffee7e976b8 
var2 Address of variable: 0 x7ffee7e976be 

Through the above example, we learned what a memory address is and how to access it. Next, let's look at what a pointer is.

What is a pointer?

A pointer is a variable whose value is the address of another variable, that is, the direct address of the memory location. Like other variables or constants, you must declare other variable addresses before using pointers to store them. The general form of pointer variable declaration is:

type *var-name 

Here, type is the base type of the pointer, it must be a valid C data type, and VaR name is the name of the pointer variable. The asterisk * used to declare the pointer is the same as the asterisk used in multiplication. However, in this statement, the asterisk is used to specify that a variable is a pointer. The following are valid pointer declarations:

int *i; //An integer pointer 
double *d;//double pointer
float *f;//Floating point pointer
char *ch//Character pointer 

All actual data types, whether integer, floating-point, character or other data types, have the same value type of the corresponding pointer, which is a long hexadecimal number representing the memory address.

The only difference between pointers of different data types is that the data types of variables or constants pointed to by the pointer are different.

How do I use pointers?

When using pointers, the following operations will be performed frequently: defining a pointer variable, assigning the variable address to the pointer, and accessing the value of the available address in the pointer variable. These return the value of the variable at the address specified by the operand by using the unary operator *****. The following examples relate to these operations:

example:

 //How to use pointers
    int var = 66;//Declaration of actual variables
    int *ip;//Declaration of pointer variables

    ip = &var; //The address where var is stored in the pointer variable
    printf("var Address of : %p  \n", var);

    //Address stored in pointer variable
    printf("ip Address of:%p  \n", ip);

    //Accessing addresses using pointers
    printf("ip Address corresponding to pointer:%p \n", *ip);

    //Use the pointer to access the value corresponding to the address
    printf("ip Address corresponding to pointer:%d \n", *ip); 

Output:

var Address of : 0x42  
ip Address: 0 x7ffee96eb6b4  
ip Address corresponding to pointer: 0 x42 
ip Address corresponding to pointer: 66 

NULL pointer in C

When a variable is declared, it is a good programming habit to assign a NULL value to a pointer variable if there is no exact address to assign. A pointer assigned a NULL value is called a NULL pointer.

A NULL pointer is a constant with a value of zero defined in the standard library. Please see the following procedure:

void main(){
    //Assign a NULL pointer
    int *ptr = NULL;
    printf("ptr Your address is: %p \n", ptr);

    //Check a null pointer
    if (ptr) printf("If ptr If it is not a null pointer, execute"); else printf("If ptr Is a null pointer");
} 

Output:

The address of ptr is 0x0. ptr is a null pointer

C pointer explanation

In C, there are many pointer related concepts. These concepts are very simple, but they are very important. Here are some important concepts related to pointers that C programmers must be aware of:

conceptdescribe
pointer arithmetic Four arithmetic operations can be performed on the pointer: + +, –, +-
Pointer arrayYou can define an array to store pointers.
Pointer to pointerC allows pointers to pointers.
Pass pointer to functionPass parameters by reference or address, so that the passed parameters are changed in the calling function.
Return pointer from functionC allows functions to return pointers to local variables, static variables, and dynamic memory allocation.

15. Function pointer and callback function

A function pointer is a pointer variable that points to a function.

Usually, the pointer variable refers to an integer, character or array variable, while the function pointer refers to a function.

Function pointers can be used to call functions and pass parameters like general functions.

Declaration of function pointer variable:

typedef int (*fun_ptr)(int,int)//Declare a function pointer type that points to the same parameter and returns the value 

example:

int max(int num1, int num2) {
    return (num1 > num2) ? num1 : num2;
}

void main() {

    //Define a function pointer with return value of int type and parameter of (int,int) form
    int (*p)(int, int) = *max;
    int a, b, c, d;
    printf("Please enter three numbers:\n");
    scanf("%d %d %d", &a, &b, &c);

    //Equivalent to direct call function, d = max(max(a,b),c);
    d = p(p(a, b), c);
    printf("The maximum number is: %d \n", d);

} 

Callback function

Function pointer variables can be used as parameters of a function. A callback function is a function called through a function pointer.

To put it simply: callback function is a function that calls your implementation when it is executed by someone else's function.

example:

In the example, populate_ The array function defines three parameters. The third parameter is the pointer of the function, which is used to set the value of the array.

In the example, we define the callback function getNextRandomValue, which returns a random value, which is passed to populate as a function pointer_ Array function.

populate_array will call the callback function 10 times and assign the return value of the callback function to the array.

#include <stdlib.h>  
#include <stdio.h>
//Callback function
void populate_array(int *array, size_t arraySize, int(*getNextValue)(void)) {
    printf("array Address:%p \n", array);
    for (size_t i = 0; i < arraySize; i++) {
        array[i] = getNextValue();
        printf(" array[%d] ,Stored value:%d \n", i, array[i]);
    }
}

//Get a random number
int getNextRandomValue(void) {
    return rand();
}

void main() {

    //Callback function
    int array[10];
    printf("Int array Address:%p \n", array);
    populate_array(array, sizeof(array)/sizeof(array[0]), getNextRandomValue);
    for (int i = 0; i < sizeof(array)/sizeof(array[0]); ++i) {
        printf(" array[%d] , The corresponding value is:%d \n", i, array[i]);
    }

} 

Output:

Int array Address: 0 x7ffeebf1a650 
array Address: 0 x7ffeebf1a650 
 array[0] ,Stored value: 16807 
 array[1] ,Stored value: 282475249 
 array[2] ,Stored value: 1622650073 
 array[3] ,Stored value: 984943658 
 array[4] ,Stored value: 1144108930 
 array[5] ,Stored value: 470211272 
 array[6] ,Stored value: 101027544 
 array[7] ,Stored value: 1457850878 
 array[8] ,Stored value: 1458777923 
 array[9] ,Stored value: 2007237709 
 array[0] , Corresponding value: 16807 
 array[1] , The corresponding value is 282475249 
 array[2] , Corresponding value: 1622650073 
 array[3] , Corresponding value: 984943658 
 array[4] , The corresponding value is 1144108930 
 array[5] , The corresponding value is 470211272 
 array[6] , The corresponding value is 101027544 
 array[7] , Corresponding value: 1457850878 
 array[8] , Corresponding value: 1458777923 
 array[9] , Corresponding value: 2007237709 

16. String

In C, a string is actually a one-dimensional character array terminated with the null character '\ 0'. Therefore, a null terminated string contains the characters that make up the string.

The following declaration and initialization creates a "Hello" string. Because empty characters are stored at the end of the array, the size of the character array is one more than the number of characters of the word "Hello".

char ch[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; 

You can also use the following abbreviation modes:

char ch[6] = "Hello" 

The string is represented in C/C + + memory:

In fact, you don't need to put null characters at the end of string constants. The C compiler will automatically put '\ 0' at the end of the string when initializing the array. Let's try to output the above string:

void main(){
      //Define a char array
    char string[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
    //Abbreviation
    char string2[6] = "Hello";
    //%s: Output string
    printf("string message : %s\n", string);
} 

Output:

string message : Hello 

API for string operation in C

Serial numberFunction & purpose
1strcpy(s1, s2); Copy string S2 to string S1.
2strcat(s1, s2); Connect string S2 to the end of string S1.
3strlen(s1); Returns the length of the string S1.
4strcmp(s1, s2); If S1 and S2 are the same, 0 is returned; If S1 < S2, it returns less than 0; If S1 > S2, it returns greater than 0.
5strchr(s1, ch); Returns a pointer to the first occurrence of the character Ch in string S1.
6strstr(s1, s2); Returns a pointer to the first occurrence of string S2 in string S1.

example:

void main(){
      //String operation
    char str1[12] = "Hello";
    char str2[12] = "World";
    char str3[12];
    int len;

    //Copy str1 to str3
    strcpy(str3, str1);
    printf("strcpy (str3,str1) :%s\n", str3);

    //Splice string str1 + str2
    strcat(str1, str2);
    printf("strcat(str1,str2) :%s\n", str1);

    //Returns the length of the string
    len = strlen(str1);
    printf("strlen(str1) :%d\n", len);
} 

Output:

strcpy (str3,str1) :Hello
strcat(str1,str2) :HelloWorld
strlen(str1) :10 

17. Structure

C array allows you to define variables that can store data items of the same type. The structure is another user-defined available data type in C programming, which allows you to store data items of different types.

Structure is used to represent a record. Assuming you want to track the dynamics of books in the library, you may need to track the following properties of each book:

  • Title
  • Author
  • Subject
  • Book ID

Define structure

To define a structure, you must use a struct statement. The struct statement defines a new data type containing multiple members. The format of the struct statement is as follows:

struct name{
  member-list;
  member-list;
  ...
}name_tag, 

name is the label of the structure.

Member list is a standard variable definition, such as int i; Or float f, or other valid variable definitions.

name_tag structure variable is defined at the end of the structure and before the last semicolon. You can specify one or more structure variables. The following is the structure method of declaring Book:

struct Books{
  char title[50];
  char author[50];
  char subject[100];
  int book_id;
} book; 

Note: when defining a structure, name, member list, and name_ At least two of these three parts of tag must appear.

Initialization of structure variables

Like other types of variables, initial values can be specified during initialization.

//Define a Books structure, which is similar to the data bean in Java
struct Books {
    char title[50];
    char author[50];
    char subject[100];
    int book_id;
    double rmb;
} book = {"Java", "Android", "C language", 666, 55.5};

void main(){
      //Print Books
    printf("title : %s\nauthor: %s\nsubject: %s\nbook_id: %d\nrmb: %f\n", book.title,
           book.author, book.subject, book.book_id, book.rmb);
} 

Output:

title : Java
author: Android
subject: C language
book_id: 666
rmb: 55.500000 

Access structure members

struct Books2 {
    char title[50];
    char author[50];
    char subject[100];
    int book_id;
};
void main(){
      //Accessing Books2 structure members
    struct Books2 Books2A;//Declare Books2A as Books2
    struct Books2 Books2B;//Declare Books2B as Books2

    //Books2A details
    strcpy(Books2A.title, "C Plus");
    strcpy(Books2A.author, "Nuha Ali");
    strcpy(Books2A.subject, "C");
    Books2A.book_id = 666888;

    //Books2B details
    strcpy(Books2B.title, "C++ Plus");
    strcpy(Books2B.author, "DevYK");
    strcpy(Books2B.subject, "C++");
    Books2B.book_id = 666999;

    // Output Book1 information
    printf("Book 1 title : %s\n", Books2A.title);
    printf("Book 1 author : %s\n", Books2A.author);
    printf("Book 1 subject : %s\n", Books2A.subject);
    printf("Book 1 book_id : %d\n", Books2A.book_id);

    // Output Book2 information
    printf("Book 2 title : %s\n", Books2B.title);
    printf("Book 2 author : %s\n", Books2B.author);
    printf("Book 2 subject : %s\n", Books2B.subject);
    printf("Book 2 book_id : %d\n", Books2B.book_id);
} 

Output:

Book 1 title : C Plus
Book 1 author : Nuha Ali
Book 1 subject : C
Book 1 book_id : 666888
Book 2 title : C++ Plus
Book 2 author : DevYK
Book 2 subject : C++
Book 2 book_id : 666999 

Structure as function parameter

//Function declaration
void printBook(struct Books2 books2);

void main(){
      //Accessing Books2 structure members
    struct Books2 Books2A;//Declare Books2A as Books2
    struct Books2 Books2B;//Declare Books2B as Books2

    //Books2A details and copy cplus into the title
    strcpy(Books2A.title, "C Plus");
    strcpy(Books2A.author, "Nuha Ali");
    strcpy(Books2A.subject, "C");
    Books2A.book_id = 666888;

    //Books2B details
    strcpy(Books2B.title, "C++ Plus");
    strcpy(Books2B.author, "DevYK");
    strcpy(Books2B.subject, "C++");
    Books2B.book_id = 666999;

    // Output Book1 information
    printf("Book 1 title : %s\n", Books2A.title);
    printf("Book 1 author : %s\n", Books2A.author);
    printf("Book 1 subject : %s\n", Books2A.subject);
    printf("Book 1 book_id : %d\n", Books2A.book_id);

    // Output Book2 information
    printf("Book 2 title : %s\n", Books2B.title);
    printf("Book 2 author : %s\n", Books2B.author);
    printf("Book 2 subject : %s\n", Books2B.subject);
    printf("Book 2 book_id : %d\n", Books2B.book_id);

    printf("\n\n\n");
    //Structure as function parameter
    printBook(Books2A);
    printBook(Books2B);
}

void printBook(struct Books2 book) {
    printf("Book  title : %s\n", book.title);
    printf("Book  author : %s\n", book.author);
    printf("Book  subject : %s\n", book.subject);
    printf("Book  book_id : %d\n", book.book_id);
} 

Output:

Book 1 title : C Plus
Book 1 author : Nuha Ali
Book 1 subject : C
Book 1 book_id : 666888
Book 2 title : C++ Plus
Book 2 author : DevYK
Book 2 subject : C++
Book 2 book_id : 666999

Book  title : C Plus
Book  author : Nuha Ali
Book  subject : C
Book  book_id : 666888
Book  title : C++ Plus
Book  author : DevYK
Book  subject : C++
Book  book_id : 666999 

Pointer to structure

You can define pointers to structures in a similar way to defining pointers to other types of variables, as follows:

struct Books *struct_pointer; 

You can now store the address of the structure variable in the pointer variable defined above. To find the address of the structure variable, put the & operator in front of the structure name, as shown below:

struct_pointer = &Book1; 

In order to access members of a structure using a pointer to the structure, you must use the - > operator, as follows:

struct_pointer->title; 

example:

//Defines a pointer to the structure
void printBookZZ(struct Books2 *books2);

void main(){
      //Accessing Books2 structure members
    struct Books2 Books2A;//Declare Books2A as Books2
    struct Books2 Books2B;//Declare Books2B as Books2

    //Books2A details and copy cplus into the title
    strcpy(Books2A.title, "C Plus");
    strcpy(Books2A.author, "Nuha Ali");
    strcpy(Books2A.subject, "C");
    Books2A.book_id = 666888;

    //Books2B details
    strcpy(Books2B.title, "C++ Plus");
    strcpy(Books2B.author, "DevYK");
    strcpy(Books2B.subject, "C++");
    Books2B.book_id = 666999;
  
     //Pass information through the memory address. In order to find the address of the structure variable, put the & operator in front of the structure name
     printBookZZ(&Books2A);
     printBookZZ(&Books2B);
} 

/**
 * In order to access members of a structure using a pointer to the structure, you must use the - > operator, as follows:
 * @param book
 */
void printBookZZ(struct Books2 *book) {
    printf("Book -> title : %s\n", book->title);
    printf("Book -> author : %s\n", book->author);
    printf("Book -> subject : %s\n", book->subject);
    printf("Book -> book_id : %d\n", book->book_id);
} 

Bit domain

When some information is stored, it does not need to occupy a complete byte, but only several or one binary bit. For example, when storing a switching value, there are only two states: 0 and 1, and 1-bit binary can be used. In order to save storage space and make processing simple, C language provides a data structure called "bit field" or "bit segment".

The so-called "bit field" is to divide the binary bit in a byte into several different regions and explain the number of bits in each region. Each domain has a domain name, which allows operations by domain name in the program. In this way, several different objects can be represented by one byte binary field.

Typical examples:

  • When storing a switching value with 1-bit binary, there are only two states: 0 and 1.
  • Read external file format - you can read non-standard file formats.

Bit field ed definition:

struct Bit field structure name{
  Bit field list
}; 

The form of bit field list is:

Type specifier bit domain name: bit domain length 

For example:

struct bean {
  int a:8;
  int b:4;
  int c:4;
}data; 

Description data is a bean variable, accounting for 2 bytes in total. Among them, bit field a accounts for 8, bit field b for 4 and bit field c for 4.

be careful:

  • A bit field is stored in the same byte. If there is not enough space left in a byte to store another bit field, the bit field will be stored from the next unit. You can also intentionally start a bit field from the next cell. For example:
struct bean{
  unsigned a:4;
  unsigned  :4;//airspace
  unsigned b:4;//Store from next unit
  unsigned c:4;
} 

a total of 2 bytes are occupied in this bit field definition. a occupies 4 bits of the first byte, and the last 4 bits are filled with 0 to indicate that it is not used. b starts from the second byte and occupies 4 bits, and c occupies 4 bits.

  • Since the bit field is not allowed to span two bytes, the length of the bit field cannot be greater than the length of one byte, that is, it cannot exceed 8-bit binary. If the maximum length is greater than the computer's integer word length, some compilers may allow domain memory overlap, while others may store parts larger than one domain in the next word.
  • The bit field can be an anonymous bit field, which is only used for filling or adjusting the position. Nameless bit fields cannot be used. For example:
struct k{
 int a:1;
 int  :2;    /* The 2 bits cannot be used */
 int b:3;
 int c:2;
}; 

From the above analysis, it can be seen that bit field is essentially a structure type, but its members are allocated according to binary.

Use of bit fields

The use of bit field is the same as that of structure member. Its general form is:

Bit field variable name Bit domain name

Bit domain variable name - > bit domain name

The bit field allows output in various formats.

example:

void main(){
       //Bit domain
     struct bs {
         unsigned int a:1;//Space occupying segment a 1 bit
         unsigned b:6;//Occupied segment b 3 bits
         unsigned c:7;//Occupied segment c 4 bits
     } bit, *pbit;
     // Assign a value to the bit field (note that the value cannot exceed the allowable range of the bit field)
     bit.a = 1; //1 bit in binary 1
     bit.b = 50;//6 bit s in binary 110010
     bit.c = 100;//Mark 7 bit s in binary 1100100
     printf("%d,%d,%d\n",bit.a,bit.b,bit.c);    // Output the contents of three fields in integer format

     pbit=&bit;     //Send the address of the bit field variable bit to the pointer variable pbit
     pbit->a=0;     //Reassign bit field a in pointer mode and assign it to 0
     pbit->b&=3;     //The compound bit operator "& =" is used, which is equivalent to: PBIT - > b = PBIT - > b & 3, the original value of bit field B is 50, and the result of bitwise sum operation with 3 is 2 (110010 & 011 = 010, decimal value is 2)
     pbit->c|=1;     //The compound bit operator "| =" is used, which is equivalent to: PBIT - > C = PBIT - > c| 1, and the result is (1100100 | 000000 1) = 1100101 = 101
     printf("%d,%d,%d\n",pbit->a,pbit->b,pbit->c);     //The values of these three fields are output in pointer mode
} 

Output:

1,50,100
0,2,101 

18. Common body

A common body is a special data type that allows you to store different data types in the same memory location. You can define a community with multiple members, but only one member can have a value at any time. Commons provide an effective way to use the same memory location.

Define community

In order to define a community, you must use a union statement in a manner similar to defining a structure. The union statement defines a new data type with multiple members. The format of the union statement is as follows:

union [union tag]
{
member definition;
member definition;
...
member definition;
}[one or more union variables]; 

union tag is optional, and each member definition is a standard variable definition, such as int i; Or float f; Or other valid variable definitions. At the end of the community definition, before the last semicolon, you can specify one or more community variables, which is optional. The following defines a common body type named Data, which has three members I, F and str:

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

Now, variables of type Data can store an integer, a floating point number, or a string. This means that a variable (the same memory location) can store multiple types of Data. You can use any built-in or user-defined Data type in a community as needed.

The memory occupied by the community should be enough to store the largest member in the community. For example, in the above example, Data will occupy 20 bytes of memory space, because the string occupies the largest space in each member. The following example shows the total memory size occupied by the above community:

union Data {
    int i;
    float f;
    char str[20];
};
void main(){
    union Data data;
    printf("Memory size occupied by data: %d\n", sizeof(data));
} 

Output:

Memory size occupied by data: 20 

Visiting community members

To access members of a community, we use the member access operator (.). The member access operator is a period between the name of the common body variable and the common body member we want to access. You can use the union keyword to define variables of the common body type. The following example demonstrates the usage of a common body:

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

void main() {
    //1. Visit the community
    data.i = 10;
    data.f = 1314.520;
    strcpy(data.str,"C/C++");
    printf( "data.i : %d\n", data.i);
    printf( "data.f : %f\n", data.f);
    printf( "data.str : %s\n", data.str);

    printf("\n\n\n");
    //2. Visit the community yes
    data.i = 10;
    printf( "data.i : %d\n", data.i);
    data.f = 1314.520;
    printf( "data.f : %f\n", data.f);
    strcpy(data.str,"C/C++");
    printf( "data.str : %s\n", data.str);
 
} 

Output:

data.i : 725823299
data.f : 0.000000
data.str : C/C++



data.i : 10
data.f : 1314.520020
data.str : C/C++ 

Here, we can see that the values of the i and f members of the common body of note 1 above are damaged, because the last value assigned to the variable occupies the memory location, which is also the reason why str members can output well. Let's look at note 2. This time, we only use one variable member at the same time, so we can output it intact.

19. Bit field

Refer to 17 (Introduction to bit field)

20. typedef

The C language provides the typedef keyword, which you can use to give a new name to the type. The following example defines a term BYTE for a single BYTE number:

typedef unsigned char BYTE; 

After this type is defined, the identifier BYTE can be used as the abbreviation of the type unsigned char, for example:

BYTE  b1, b2; 

By convention, upper case letters are used to remind users that the type name is a symbolic abbreviation, but you can also use lower case letters, as follows:

typedef unsigned char byte; 

You can also use typedef to give a new name to a user-defined data type. For example, you can use typedef to define a new data type name for a structure, and then use this new data type to directly define structure variables, as follows:

typedef struct Books {
    char title[50];
    char author[50];
    char subject[50];
    int book_id;
} Book;

#define TRUE  1
#define FALSE  0

 void main(){
     Book book;
     strcpy( book.title, "C course");
     strcpy( book.author, "Runoob");
     strcpy( book.subject, "programing language");
     book.book_id = 12345;
     printf( "Book title : %s\n", book.title);
     printf( "Book author : %s\n", book.author);
     printf( "Book category : %s\n", book.subject);
     printf( "book ID : %d\n", book.book_id);

     printf( "TRUE Value of: %d\n", TRUE);
     printf( "FALSE Value of: %d\n", FALSE);
 } 

Output:

Book title : C course
 Book author : Runoob
 Book category : programing language
 book ID : 12345
TRUE Value of: 1
FALSE Value of: 0 

typedef vs define

Define is a C instruction used to define aliases for various data types. It is similar to typedef, but they have the following differences:

  • typedef is limited to defining symbol names for types, #define can define aliases not only for types, but also for values. For example, you can define 1 as ONE.
  • typedef is interpreted by the compiler, and #define statements are processed by the precompiler.

For example, the above is #define.

21. Input & output

When we mention input, this means filling the program with some data. Input can be in the form of a file or from the command line. C language provides a series of built-in functions to read the given input and fill it into the program as needed.

When we talk about output, this means displaying some data on the screen, on the printer, or in any file. C language provides a series of built-in functions to output data to the computer screen and save data to text files or binary files.

standard output

C language treats all devices as files. Therefore, devices (such as displays) are processed in the same way as files. The following three files are automatically opened when the program is executed to access the keyboard and screen.

Standard documentsfield name pointerequipment
Standard inputstdinkeyboard
standard output stdoutscreen
Standard errorstderrYour screen

File pointers are the way to access files. This section explains how to read values from the screen and output results to the screen.

I/O (input / output) in C language usually uses printf() and scanf().

The scanf() function is used to read and format from standard input (keyboard), and the printf() function sends formatted output to standard output (screen).

example:

void main(){
      float f;
    printf("Enter a float number: \n");
    // %f match floating point data
    scanf("%f",&f);
    printf("Value = %f", f);
} 

Output:

Enter a float number: 
12.3
Value = 12.300000 

Getchar() & putchar() function

The int getchar(void) function reads the next available character from the screen and returns it as an integer. This function reads only one single character at a time. You can use this method within a loop to read multiple characters from the screen.

The int putchar(int c) function outputs characters to the screen and returns the same characters. This function will only output a single character at the same time. You can use this method within a loop to output multiple characters on the screen.

void main(){
    int c;
    printf( "\nEnter a value :");
    //Function reads the next available character from the screen and returns it as an integer. This function reads only one single character at a time. You can use this method within a loop to read multiple characters from the screen.
    c = getchar( );
    printf( "\nYou entered: ");
    //Read first character
    putchar( c );
} 

Output:

Enter a value :abcdef

You entered: a 

Gets () & puts () function

The char *gets(char *s) function reads a line from stdin to the buffer pointed to by s until a terminator or EOF.

The int puts(const char *s) function writes the string s and a trailing newline character to stdout.

void main(){
    char str[100];

    printf( "\nEnter a value :");
    //Read one line
    gets( str );

    printf( "\nYou entered: ");
    puts( str );
} 

Output:

Enter a value :Hello everyone, it's really good!

You entered: Hello everyone, it's really good! 

22. Document reading and writing

In the last section, we explained the standard input and output devices of C language processing. In this chapter, we will introduce how C programmers create, open and close text files or binary files.

A file, whether it is a text file or a binary file, represents a series of bytes. C language not only provides access to top-level functions, but also provides bottom-level (OS) calls to process files on storage devices. This chapter will explain the important call of document management.

Open file

You can use the fopen() function to create a new FILE or open an existing FILE. This call will initialize an object of type FILE, which contains all the necessary information to control the flow. The following is the prototype of this function call:

FILE *fopen( const char * filename, const char * mode ); 

Here, filename is a string used to name the file. The value of access mode can be one of the following values:

patterndescribe
rOpen an existing text file to allow reading of the file.
wOpen a text file to allow writing to the file. If the file does not exist, a new file is created. Here, your program writes from the beginning of the file. If the file exists, it will be truncated to zero length and written again.
aOpen a text file and write the file in append mode. If the file does not exist, a new file is created. Here, your program will add content to the existing file content.
r+Open a text file to allow reading and writing files.
w+Open a text file to allow reading and writing files. If the file already exists, the file is truncated to zero length, and if the file does not exist, a new file is created.
a+Open a text file to allow reading and writing files. If the file does not exist, a new file is created. Reading starts at the beginning of the file, and writing can only be in append mode.

If you are dealing with binary files, you need to use the following access mode to replace the above access mode:

"rb", "wb", "ab", "rb+", "r+b", "wb+", "w+b", "ab+", "a+b" 

Close file

To close the file, use the fclose() function. The prototype of the function is as follows:

 int fclose( FILE *fp ); 

The fclose() function returns zero if the file is closed successfully, and EOF if an error occurs when the file is closed. This function actually empties the buffer, closes the file, and frees all memory for the file. EOF is defined in the header file stdio Constant in H.

C standard library provides various functions to read and write files by characters or in the form of fixed length strings.

write file

The following is the simplest function to write a string to a stream:

int fputc(int c,FILE *fp); 

The function fputc() writes the character value of parameter c to the output stream pointed to by fp. If the writing is successful, it will return the written character, and if an error occurs, it will return EOF. You can use the following function to write a null terminated string to the stream:

int fputs( const char *s, FILE *fp ); 

The function fputs() writes the string s to the output stream pointed to by fp. It returns a non negative value if the write is successful and EOF if an error occurs. You can also use the int fprintf(FILE *fp,const char *format,...) function to write a string to a file. Try the following example:

void main(){
      //Define a null pointer file
    FILE *fp = NULL;
    //Open file, open a text file, and allow reading and writing files.
    // If the file does not exist, a new file is created.
    // Reading starts at the beginning of the file, and writing can only be in append mode.
    fp = fopen("/Users/devyk/Data/ClionProjects/NDK_Sample/README.md","a+");
    fprintf(fp, " fprintf I'm an added 1\n");
    fprintf(fp, "fprintf I added 2\n");
    fputs("fputs I'm an added 1\n", fp);
    fputs("fputs I added 2\n", fp);
    fclose(fp);
} 

read file

The following is the simplest function to read a single character from a file:

int fgetc( FILE * fp ); 

The fgetc() function reads a character from the input file pointed to by fp. The return value is the read character. If an error occurs, EOF is returned. The following function allows you to read a string from the stream:

char *fgets( char *buf, int n, FILE *fp ); 

The function fgets() reads n - 1 characters from the input stream pointed to by fp. It copies the read string to the buffer buf and appends a null character at the end to terminate the string.

If this function encounters a newline '\ n' or EOF at the end of the file before reading the last character, it will only return the read characters, including the newline character. You can also use the int fscanf(FILE *fp, const char *format,...) function to read a string from a file, but it stops reading when the first space and newline character are encountered.

example:

void main(){
    FILE *fp = NULL;
    //read file
    char buff[255];
    fp = fopen("/Users/devyk/Data/ClionProjects/NDK_Sample/README.md","r");
    fscanf(fp,"%s",buff);
    printf("1: %s\n", buff);

    fgets(buff, 255, (FILE*)fp);
    printf("2: %s\n", buff);

    fgets(buff, 255, (FILE*)fp);
    printf("3: %s\n", buff );
    fclose(fp);
} 

23. Preprocessor

The C Preprocessor is not part of the compiler, but it is a separate step in the compilation process. In short, the C Preprocessor is just a text replacement tool that instructs the compiler to complete the required preprocessing before the actual compilation. We will abbreviate C Preprocessor to CPP.

All preprocessor commands begin with a pound sign (#). It must be the first non null character. To enhance readability, preprocessor instructions should start from the first column. All important preprocessor instructions are listed below:

instructionsdescribe
#defineDing Yihong
#includeContains a source code file
#undefCancel defined macros
#ifdefReturns true if the macro is already defined
#ifndefReturns true if the macro is not defined
#ifIf the given condition is true, compile the following code
#else#if alternative
#elifIf the #if given condition is not true and the current condition is true, compile the following code
#endifEnd a #if... #else conditional compilation block
#errorWhen a standard error is encountered, an error message is output
#pragmaUse standardized methods to issue special commands to the compiler

example:

Analyze the following examples to understand the different instructions.

#define MAX_ARRAY_LENGTH 20 

This instruction tells CPP to send all Max_ ARRAY_ Replace length with 20. Use #define to define constants to enhance readability.

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

These instructions tell CPP to get stdio from the system library h. And add text to the current source file. The next line tells CPP to get utils from the local directory h. And add content to the current source file.

#undef  FILE_SIZE
#define FILE_SIZE 42 

This instruction tells CPP to cancel the defined FILE_SIZE and define it as 42.

#ifndef MESSAGE
   #define MESSAGE "You wish!"
#endif 

This instruction tells CPP to define MESSAGE only when MESSAGE is undefined.

#ifdef DEBUG
   /* Your debugging statements here */
#endif 

This instruction tells CPP to execute the processing statement if DEBUG is defined. At compile time, this instruction is useful if you pass the - DDEBUG switch to the gcc compiler. It defines DEBUG, which you can turn on or off at any time during compilation.

macros predefined

ANSI C defines many macros. You can use these macros in programming, but you cannot directly modify these predefined macros.

macrodescribe
DATECurrent date, a character constant in the format "MMM DD YYYY".
TIMECurrent time, a character constant in "HH:MM:SS" format.
FILEThis will contain the current file name, a string constant.
LINEThis will contain the current line number, a decimal constant.
STDCWhen the compiler is compiled in ANSI standard, it is defined as 1.

example:

void main() {
    //This will contain the current file name, a string constant.
    printf("File :%s\n", __FILE__);
    //Current date, a character constant in the format "MMM DD YYYY".
    printf("Date :%s\n", __DATE__);
    //Current time, a character constant in "HH:MM:SS" format.
    printf("Time :%s\n", __TIME__);
    //This will contain the current line number, a decimal constant.
    printf("Line :%d\n", __LINE__);
    //When the compiler is compiled in ANSI standard, it is defined as 1.
    printf("ANSI :%d\n", __STDC__);
} 

Output:

File :/Users/devyk/Data/ClionProjects/NDK_Sample/day_1/ndk_day1.c
Date :Dec 17 2019
Time :14:23:47
Line :954
ANSI :1 

Preprocessor operator

The C preprocessor provides the following operators to help you create macros:

Macro continuation operator ()

A macro is usually written on a single line. However, if the macro is too long to fit a single line, the macro continuation operator (\) is used. For example:

#define  message_for(a, b)  \
    printf(#a " and " #b ": We love you!\n") 

String constant quantization operator (#)

In the macro definition, when the parameters of a macro need to be converted into string constants, the string constant quantization operator (#) is used. The operator used in the macro has a specific parameter or parameter list. For example:

#include <stdio.h>

#define  message_for(a, b)  \
    printf(#a " and " #b ": We love you!\n")

int main(void) {
   message_for(Carole, Debra);
   return 0;
} 

When the above code is compiled and executed, it will produce the following results:

Carole and Debra: We love you! 

Tag paste operator (##)

The tag paste operator (##) within the macro definition combines the two parameters. It allows two independent tags to be merged into one tag in the macro definition. For example:

#include <stdio.h>

#define tokenpaster(n) printf ("token" #n " = %d", token##n)

int main(void) {
   int token34 = 40;
   
   tokenpaster(34);
   return 0;
} 

When the above code is compiled and executed, it will produce the following results:

token34 = 40 

How does this happen because this instance produces the following actual output from the compiler:

printf ("token34 = %d", token34); 

This example demonstrates that token##n will be connected to token34. Here, we use string constant quantization operator (#) and tag paste operator (##).

defined() operator

The preprocessor defined operator is used in constant expressions to determine whether an identifier has been defined with #define. If the specified identifier is defined, the value is true (non-zero). If the specified identifier is undefined, the value is false (zero). The following example demonstrates the use of the defined() operator:

#include <stdio.h>

#if !defined (MESSAGE)
   #define MESSAGE "You wish!"
#endif

int main(void) {
   printf("Here is the message: %s\n", MESSAGE);  
   return 0;
} 

When the above code is compiled and executed, it will produce the following results:

Here is the message: You wish! 

Parameterized macro

A powerful feature of CPP is that you can use parameterized macros to simulate functions. For example, the following code calculates the square of a number:

int square(int x) {
   return x * x;
} 

We can rewrite the above code with macros as follows:

#define square(x) ((x) * (x)) 

Before using a macro with parameters, you must define it with the #define directive. The parameter list is enclosed in parentheses and must follow the macro name. No spaces are allowed between the macro name and the left parenthesis. For example:

#include <stdio.h>

#define MAX(x,y) ((x) > (y) ? (x) : (y))

int main(void) {
   printf("Max between 20 and 10 is %d\n", MAX(10, 20));  
   return 0;
} 

When the above code is compiled and executed, it will produce the following results:

Max between 20 and 10 is 20 

24. Header file

The header file has an extension of h, which contains C function declarations and macro definitions, is referenced and shared by multiple source files. There are two types of header files: the header file written by the programmer and the header file provided by the compiler.

To use a header file in a program, you need to use the C preprocessing instruction #include to reference it. We've seen stdio before H header file, which is the header file of the compiler.

Referencing a header file is equivalent to copying the contents of the header file, but we will not directly copy the contents of the header file in the source file, because it is easy to make mistakes, especially when the program is composed of multiple source files.

In A simple practice in C or C + + programs, it is recommended to write all constants, macros, system global variables and function prototypes in header files, and reference these header files at any time when necessary.

Syntax for referencing header files

Use the preprocessing directive #include to reference user and system header files. It has the following two forms:

#include <file> 

This form is used to reference system header files. It searches the standard list of system directories for a file named file. When compiling source code, you can use the - I option to bring the directory before the list.

#include "file" 

This form is used to reference the user header file. It searches the directory containing the current file for a file named file. When compiling source code, you can use the - I option to bring the directory before the list.

Operation of referencing header file

#The include instruction instructs the C preprocessor to browse the specified file as input. The output of the preprocessor includes the generated output, the output generated by the referenced file, and the text output after the #include instruction. For example, if you have a header file char_manger.h. As follows:

char *test(void); 

And a main program char that uses a header file_ manager. c. As follows:

#include "char_manger.h"
int x;
int main (void) {
   puts (test ());
} 

The editor will see the following code information:

char *test (void);

int x;

int main (void) {
   puts (test ());
} 

The header file is referenced only once

If a header file is referenced twice, the compiler will process the contents of the header file twice, which will produce an error. In order to prevent this situation, the standard practice is to put the whole content of the file in the conditional compilation statement, as follows:

#ifndef HEADER_FILE
#define HEADER_FILE

the entire header file file

#endif 

This structure is commonly known as the wrapper #ifndef. When the header file is referenced again, the condition is false because HEADER_FILE is already defined. At this point, the preprocessor skips the entire contents of the file and the compiler ignores it.

Conditional reference

Sometimes it is necessary to select a reference from multiple different header files into the program. For example, you need to specify configuration parameters to use on different operating systems. You can achieve this through a series of conditions, as follows:

#if SYSTEM_1
   # include "system_1.h"
#elif SYSTEM_2
   # include "system_2.h"
#elif SYSTEM_3
   ...
#endif 

However, if there are many header files, it is not appropriate to do so. The preprocessor uses macros to define the name of the header file. This is called conditional reference. Instead of using the name of the header file as #include's direct parameter, you just need to use the macro name instead:

 #define SYSTEM_H "system_1.h"
 ...
 #include SYSTEM_H 

SYSTEM_H will expand and the preprocessor will look for system_1.h, as #include originally wrote. SYSTEM_H can be defined by your Makefile with the - D option

25. Cast type

Cast is to convert a variable from one type to another data type. For example, if you want to store a value of long type into a simple integer, you need to cast long type to int type. You can use the cast operator to explicitly convert a value from one type to another, as follows:

(type_name) expression 

See the following example. Use the cast operator to divide an integer variable by another integer variable to obtain a floating-point number:

void main(){
   void main(){
     int sum = 20,count = 3;
     double  value,value2;
    value = (double)sum / count;
    value2 = sum / count;
    printf("Value Strong rotation : %f Value2 wei Strong rotation : %f\n ", value ,value2);
 }
} 

Output:

Value Strong rotation : 6.666667 Value2 wei Strong rotation : 6.000000 

Integer lifting

Integer promotion refers to the process of converting an integer type less than int or unsigned int to int or unsigned int. See the following example to add a character to int:

void main(){
  
    //Integer promotion
    int i= 17;
    char c = 'c'; //The value in ascii represents 99
    int sum2;

    sum2 = i + c;
    printf("Value of sum : %d\n", sum2 );
} 

Output:

 Value of sum : 116 

Here, the value of sum is 116, because the compiler performs integer promotion and converts the value of 'c' to the corresponding ascii value when performing the actual addition operation.

26. Error handling

C language does not provide direct support for error handling, but as a system programming language, it allows you to access the underlying data in the form of return values. When an error occurs, most C or UNIX function calls return 1 or NULL, and an error code errno is set. The error code is a global variable, indicating that an error occurred during the function call. You can use errno Various error codes are found in the H header file.

Therefore, C programmers can check the return value and then decide which appropriate action to take according to the return value. Developers should set errno to 0 when the program is initialized, which is a good programming habit. A value of 0 indicates that there are no errors in the program.

errno, perror() and strerror()

C language provides perror() and strerror() functions to display text messages related to errno.

  • The perror() function displays the string you passed it, followed by a colon, a space, and a textual representation of the current errno value.
  • strerror() function, which returns a pointer to the text representation of the current errno value.

Let's simulate an error situation and try to open a file that doesn't exist. You can output error messages in a variety of ways. Here we use functions to demonstrate usage. Another thing to note is that you should use the stderr file stream to output all errors.

example:

void main(){
    int dividend = 20;
    int divsor = 0;
    int quotient;

    if (divsor == 0){
        fprintf(stderr,"Divisor 0 quit running...\n");
        exit(EXIT_FAILURE);
    }
    quotient = dividend / divsor;
    fprintf(stderr,"quotient The value of the variable is : %d\n", quotient);
    exit(EXIT_SUCCESS);
} 

Output:

Divisor 0 quit running... 

27. Recursion

Recursion refers to the method of using the function itself in the definition of a function.

The syntax format is as follows:

void recursion() {
   statements;
   ... ... ...
   recursion(); /* Function call itself */
   ... ... ...
}
 
int main() {
   recursion();
} 

Factorial of number

double factorial(unsigned int i){
    if (i <= 1){
        return 1;
    }
   return i * factorial(i - 1);
}
void main(){
    int i = 15;
    printf("%d factorial  %ld \n",i ,factorial(i));
} 

Output:

15 Factorial 1407327129776 

fibonacci sequence

//fibonacci sequence 
int fibonaci(int i){
    if (i == 0){
        return 0;
    }
    if (i == 1){
        return 1;
    }
    return fibonaci(i - 1) + fibonaci( i -2);
}
void main(){
    for (int j = 0; j < 10; j++) {
        printf("%d\t\n", fibonaci(j));

    }
} 

Output:

0
1	
1	
2	
3	
5	
8	
13	
21	
34 

28. Variable parameters

Sometimes you may encounter situations where you want a function to have a variable number of parameters instead of a predefined number of parameters. The C language provides a solution to this situation, which allows you to define a function that can accept a variable number of parameters according to specific needs. The following example demonstrates the definition of this function.

int func(int, ... ) {
   .
   .
   .
}
 
int main() {
   func(2, 2, 3);
   func(3, 2, 3, 4);
} 

Note that the last parameter of func() is written as an ellipsis, that is, three periods (...). The parameter before the ellipsis is int, which represents the total number of variable parameters to be passed. To use this function, you need to use stdarg H header file, which provides functions and macros to realize variable parameter function. The specific steps are as follows:

  • Define a function. The last parameter is an ellipsis. User defined parameters can be set before the ellipsis.
  • Create a VA in the function definition_ List type variable, which is in stdarg H is defined in the header file.
  • Use int parameters and va_start macro to initialize VA_ The list variable is a list of parameters. Macro va_start is in stdarg H is defined in the header file.
  • Use va_arg macro and va_list variable to access each item in the parameter list.
  • Use macro va_end to clean up_ Memory of the list variable.

Now let's follow the above steps to write a function with a variable number of parameters and return their average value:

example:

 double average(int num,...){
     va_list  vaList;
     double  sum = 0.0;
     int i ;
     //Initialize valist for num parameters
     va_start(vaList,num);
     //Access all parameters assigned to the vaList
    for (int j = 0; j < num; j++) {
        sum += va_arg(vaList, int);
    }
    //Clean up memory reserved for valist
    va_end(vaList);
    return sum/num;
 }

 void main(){
     printf("Average of 2, 3, 4, 5 = %f\n", average(4, 2,3,4,5));
     printf("Average of 5, 10, 15 = %f\n", average(3, 5,10,15));
 } 

Output:

Average of 2, 3, 4, 5 = 3.500000
Average of 5, 10, 15 = 10.000000 

29. Memory management

This chapter will explain dynamic memory management in C. C language provides several functions for memory allocation and management. These functions can be found in < stdlib h> Found in header file.

Serial numberFunctions and descriptions
*void calloc(int num, int size);_ Dynamically allocate num consecutive spaces with length of size in memory, and initialize each byte to 0. So the result is that num is allocated_ Size is a byte long memory space, and the value of each byte is 0.
void free(void *address);This function releases the memory block pointed to by address, and the dynamically allocated memory space is released.
void *malloc(int num);Allocate a memory space of a specified size in the heap to store data. This memory space will not be initialized after the function is executed, and their values are unknown.
void *realloc(void *address, int newsize);This function reallocates memory and expands memory to new size.

**Note: * * void * type indicates pointer of undetermined type. C. C + + specifies that the void * type can be cast to any other type of pointer through type conversion.

Dynamically allocate memory

When programming, if you know the size of the array in advance, it is easier to define the array. For example, an array that stores people's names can hold up to 100 characters, so you can define the array as follows:

char name[100]; 

However, if you don't know the length of text to store in advance, for example, you can store a detailed description of a topic. Here, we need to define a pointer that points to characters whose required memory size is not defined, and then allocate memory according to requirements, as shown below:

void main() {
    char name[100];
    char *description;

    //copy the string to name
    strcpy(name, "Marry Bai Fumei!");

    //Start dynamic memory allocation
    description = (char *) malloc(200 * sizeof(char));
    if (description == NULL) {
        fprintf(stderr, "Error - unable to allocate required memory\n");
    } else {
        strcpy(description, "Start adding data to description in");
    }
    printf("Name = %s\n", name );
    printf("Description: %s sizeOf size:%d\n", description , sizeof(description));
//     Use the free() function to free memory
    free(description);
} 

Output:

Name = Marry Bai Fumei!
Description: Start adding data to description in sizeOf Size: 8 

30. Command line parameters

When executing the program, you can pass values from the command line to the C program. These values are called command line parameters and are important to the program, especially when you want to control the program from the outside rather than hard code these values within the code.

Command line parameters are processed using the main() function parameters, where argc refers to the number of parameters passed in, and argv [] is a pointer array pointing to each parameter passed to the program. The following is a simple example to check whether the command line provides parameters and perform corresponding actions according to the parameters:

void main(int argc , char *argv[]){
    if (argc ==1){
        printf("argv[%d] == %d",0,*argv[0]);
    }
    else if (argc ==2){
        printf("argv[%d] == %d",1,*argv[1]);
    } else{
        printf("Matching failed...");
    }
} 

Output:

argv[0] == 47 

summary

I don't know if most of the Java grammars are the same after reading the basic content of C. some people said that learning other languages after learning C is a piece of cake. Now it seems like this. Personally, I think it will be easier to learn any one of the programming languages while learning other languages.

C language foundation strengthening learning materials

reference resources

This article is transferred from https://juejin.cn/post/6844904022827073543 , in case of infringement, please contact to delete# last

There is a private letter from a small partner asking the question of Compose. Is it easy to use? Do you want to learn it now?

In fact, the answer is very simple. Since Google announced the declarative UI framework Jetpack Compose in 2019, API functions have stabilized after more than two years of vigorous publicity and inclination of a large number of resources.

As for whether it is easy to use, all kinds of used peers hold a positive attitude. The advantages are probably these four points:

Powerful tools and intuitive Kotlin API
Simplifies and accelerates UI development on Android
It can help developers create views with less and more intuitive code
It has more powerful functions and can improve the development speed

There is no doubt that such a great advantage must be learned, and the sooner you master it, the better. Don't wait until the knife rest is on your neck to practice the golden bell jar.

As for how to get started quickly, you can share a * * Jetpack Compose complete development manual * * for free to teach you from getting started to mastering.

Chapter 1 getting to know Jetpack Compose

  • Why do we need a new UI tool?

  • Jetpack Compose focus

    Accelerate development
    Powerful UI tools
    Intuitive Kotlin API

  • API design

  • Principles of Compose API
    Everything is a function
    Top level function
    Combination is better than inheritance
    Trust a single source

  • Learn more about Compose
    Core
    Foundation
    Material

  • Slot API

Chapter 2 building Android UI with Jetpack Compose

  • Android Jetpack Compose most complete Getting Started Guide
    Jetpack Compose environment preparation and Hello World
    layout
    Design with Material design
    Composite layout live preview
    ......

  • In depth explanation of jetpack composition | optimizing UI construction
    Problems solved by Compose
    Analysis of Composable function
    Declarative UI
    Combination vs inheritance
    encapsulation
    recombination
    ......

  • Thoroughly explain the implementation principle of Jetpack Compose |
    @What does the Composable annotation mean?
    Execution mode
    Positional memory
    Storage parameters
    recombination
    ......

Chapter III actual combat drill of Jetpack Compose project (with Demo)

  • Jetpack Compose app 1
    Preparation before start
    Create DEMO
    Problems encountered

  • Jetpack Compose app 2
  • The Jetpack Compose application is used as a countdown timer
    data structure
    Countdown function
    State mode
    Compose layout
    Draw clock

  • Write an android App with Jetpack Compose
    preparation
    Introduce dependency
    New Activity
    Create composite
    PlayTheme
    Draw page
    Bottom navigation bar
    Management status
    Add page

  • Write a weather app with Compose Android
    Opening
    Draw page
    Painting background
    Painting content
    ......

  • Quickly create a "movie App" with Compose
    finished product
    Implementation scheme
    actual combat
    Insufficient
    ......

Due to space constraints, the detailed information of the document is too comprehensive and there are too many details, so only the screenshots of some knowledge points are roughly introduced. There are more detailed contents in each small node!

Detailed documents can Click me to download for free , remember to like it~

Topics: Android Interview Programmer kotlin Optimize