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:
- 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.
- The next line /.... / will be ignored by the compiler, where the comments of the program are placed. They are called program annotations.
- The next line, int main(), is the main function from which the program starts.
- 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.
- 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).
keyword | explain |
---|---|
auto | Declare automatic variables |
break | Jump out of current loop |
case | Switch statement branch |
char | Declare the return value type of a character variable or function |
const | Declare only readable variables |
continue | End the current cycle and start the next cycle |
default | Other branches in switch statements |
do | The body of a loop statement |
double | Declare a double progress floating-point variable or function return value type |
else | Conditional statement negative branch |
enum | Declare enumeration type |
extern | Declare that variables or functions are defined in other documents or elsewhere in this document |
float | Declare the return value type of a floating-point variable or function |
for | A circular statement |
goto | Unconditional jump statement |
if | Conditional statement |
int | Declare an integer variable or function |
long | Declare the return value type of a long integer variable or function |
register | Declare register variables |
return | Subroutine return statement |
short | Declare a short integer variable or function |
signed | Declare a variable or function of signed type |
sizeof | Calculate the data type or variable length (i.e. the number of bytes) |
static | Declare static variables |
struct | Declare structure type |
switch | For switch statements |
typedef | Used to alias data types |
unsigned | Declare an unsigned variable or function |
union | Declare common body type |
void | The declared function has no return value or parameter tree, and the declared function has no type pointer |
volatile | Description variables can be changed implicitly during program execution |
while | Loop 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:
type | explain |
---|---|
Basic type | They are arithmetic types, including two types: integer type and floating point type. |
Enumeration type | They are also arithmetic types and are used to define variables that can only be given a certain discrete integer value in the program. |
void type | The type specifier void table name has no available values |
Derived type | They 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
type | 32 bit | 64 bit | Value range |
---|---|---|---|
char | 1 | 1 | -128 to 127 or 0 to 255 |
unsigned char | 1 | 1 | 0 to 255 |
int | 4 | 4 | -32768 to 32767 or - 2147483648 to 2147483647 |
unsigned int | 4 | 4 | 0 to 65535 or 0 to 4294967295 |
short | 2 | 2 | -32768 to 32767 |
unsigned short | 2 | 2 | 0 to 65535 |
long | 4 | 8 | -2147483648 to 2147483647 |
unsigned long | 4 | 8 | 0 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
type | Number of bits | Significant number | Value range |
---|---|---|---|
float | 4 | 6~7 | 1.2E-38 to 3.4E+38 |
double | 8 | 15~16 | 2.3E-308 to 1.7E+308 |
long double | 16 | 18~19 | 3.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 controller | explain |
---|---|
%c | Read a single character |
%hd,%d,%ld | Read a decimal integer and assign it to short, int and long types respectively |
%ho,%o,%lo | Read an octal integer (with or without prefix) and assign it to types short, int and long respectively |
%hx,%x,%lx | Read a hexadecimal integer (with or without prefix) and assign it to types short, int and long respectively |
%hu,%u,%lu | Read an unsigned integer and assign it to unsigned short, unsigned int and unsigned long types respectively |
%f,%lf | Read a decimal number in decimal form and assign it to float and double types respectively |
%e,%le | Read a decimal in exponential form and assign it to float and double types respectively |
%g,%lg | You can read either a decimal decimal or an exponential decimal and assign them to float and double types respectively |
%s | Read 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:
- Use #define preprocessor.
- 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:
operator | describe | example |
---|---|---|
+ | Add the two operands | A + B will get 30 |
- | Subtracts the second operand from the first operand | A - B will get - 10 |
* | Multiply two operands | A * B will get 200 |
/ | Numerator divided by denominator | B / A will get 2 |
% | Modulo operator, remainder after division | B% a will get 0 |
++ | Self increasing operator, the integer value is increased by 1 | A + + will get 11 |
– | Self subtraction operator, the integer value is reduced by 1 | A -- 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:
operator | describe | example |
---|---|---|
== | 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:
operator | describe | example |
---|---|---|
&& | 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:
operator | describe | example |
---|---|---|
& | 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:
operator | describe | example |
---|---|---|
= | A simple assignment operator assigns the value of the right operand to the left operand | C = 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 operand | C += 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 operand | C -= 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 operand | C *= 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 operand | C /= 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 operand | C% = a is equivalent to C = C% a |
<<= | Shift left and assignment operator | C < < 2 is equivalent to C = C < < 2 |
>>= | Shift right and assignment operator | C > > = 2 is equivalent to C = C > > 2 |
&= | Bitwise AND and assignment operator | C & = 2 is equivalent to C = C & 2 |
^= | Bitwise exclusive or and assignment operator | C ^= 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?:.
operator | describe | example |
---|---|---|
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 expression | If 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.
sentence | describe |
---|---|
if statement | An if statement consists of a Boolean expression followed by one or more statements. |
if... else statement | An if statement can be followed by an optional else statement, which is executed when the Boolean expression is false. |
Nested if statement | You can use another if or else if statement within one if or else if statement. |
switch statement | A switch statement allows you to test when a variable is equal to multiple values. |
Nested switch statements | You 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 type | describe |
---|---|
while loop | When the given condition is true, repeat the statement or statement group. It tests the condition before executing the loop body. |
for loop | Execute a statement sequence multiple times to simplify the code for managing loop variables. |
do... while loop | It is similar to the while statement except that it tests the condition at the end of the loop body. |
Nested loop | You 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 statement | describe |
---|---|
break statement | When the loop or switch statement is terminated, the program flow will continue to execute the next statement following the loop or switch. |
continue statement | Tell a loop body to stop this loop iteration immediately and restart the next loop iteration. |
goto statement | Transfers 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 type | describe |
---|---|
Value passing call | This 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 call | Through 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:
- A local variable inside a function or block
- Global variables outside all functions
- 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 type | Initialize defaults |
---|---|
int | 0 |
char | '\0' |
float | 0 |
double | 0 |
pointer | NULL |
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:
concept | describe |
---|---|
Multidimensional array | C supports multidimensional arrays. The simplest form of multidimensional array is two-dimensional array. |
Pass array to function | You can pass a pointer to the array to the function by specifying an array name without an index. |
Returns an array from a function | C allows an array to be returned from a function. |
Pointer to array | You 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 Enumeration name {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:
concept | describe |
---|---|
pointer arithmetic | Four arithmetic operations can be performed on the pointer: + +, –, +- |
Pointer array | You can define an array to store pointers. |
Pointer to pointer | C allows pointers to pointers. |
Pass pointer to function | Pass parameters by reference or address, so that the passed parameters are changed in the calling function. |
Return pointer from function | C 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 number | Function & purpose |
---|---|
1 | strcpy(s1, s2); Copy string S2 to string S1. |
2 | strcat(s1, s2); Connect string S2 to the end of string S1. |
3 | strlen(s1); Returns the length of the string S1. |
4 | strcmp(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. |
5 | strchr(s1, ch); Returns a pointer to the first occurrence of the character Ch in string S1. |
6 | strstr(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 documents | field name pointer | equipment |
---|---|---|
Standard input | stdin | keyboard |
standard output | stdout | screen |
Standard error | stderr | Your 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:
pattern | describe |
---|---|
r | Open an existing text file to allow reading of the file. |
w | Open 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. |
a | Open 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:
instructions | describe |
---|---|
#define | Ding Yihong |
#include | Contains a source code file |
#undef | Cancel defined macros |
#ifdef | Returns true if the macro is already defined |
#ifndef | Returns true if the macro is not defined |
#if | If the given condition is true, compile the following code |
#else | #if alternative |
#elif | If the #if given condition is not true and the current condition is true, compile the following code |
#endif | End a #if... #else conditional compilation block |
#error | When a standard error is encountered, an error message is output |
#pragma | Use 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.
macro | describe |
---|---|
DATE | Current date, a character constant in the format "MMM DD YYYY". |
TIME | Current time, a character constant in "HH:MM:SS" format. |
FILE | This will contain the current file name, a string constant. |
LINE | This will contain the current line number, a decimal constant. |
STDC | When 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 number | Functions 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~