lark

next

Code Create Life
telegram
tg_channel
x
github
zhihu
email
follow

C Language Programming

[Code Download](https://cloud.189.cn/t/eqauAb7f2i2y(Access Code: 7x3g))

Basic Concepts of Program Design#

Characteristics of Algorithms#

  1. Finiteness: An algorithm must terminate after a finite number of steps and will not enter an infinite loop or deadlock.
  2. Definiteness: Each step of the algorithm must be clearly defined and unambiguous. The same input should produce the same output.
  3. Executability: Each step in the algorithm must be executable and should not include operations that cannot be performed.
  4. Zero or more inputs: An algorithm can accept zero or more input parameters, which are the input data for the problem.
  5. One or more outputs: An algorithm produces one or more output results, which are the solutions to the problem.

Three Basic Structures#

Algorithms composed of three basic structures can solve any complex problem.

  1. Sequential structure: Statements in the program are executed in order, from top to bottom, with each statement executed once.
  2. Selection structure: The selection structure allows different code blocks to be executed based on the truth value of conditions. This includes if statements and switch statements, etc. For example, using an if statement allows different code blocks to be executed based on conditions, thus implementing branching logic.
    if (condition) {
    // Code Block 1
    } else {
    // Code Block 2
    }
    
  3. Loop structure: The loop structure allows the same code block to be executed multiple times until a specific condition is met. This can be achieved through loop statements such as for, while, and do-while.
    while (condition) {
    // Code to be executed in the loop
    }
    
    for (int i = 0; i < n; i++) {
    // Code to be executed in the loop
    }
    

Chapter Two Preliminary Understanding of C Programming#

2.1 Composition and Format of Simple C Language Programs#

/* Calculate the area of a rectangle */
#include "stdio.h"  
  
int main() {  
	double a, b, area;  
	a = 1.2; /* Assign the lengths of the two sides of the rectangle to a and b */  
	b = 3.6;  
	area = a * b; /* Calculate the area of the rectangle and store it in the variable area */  
	printf("a=%f,b=%f,area=%f\n", a, b, area);  
}
  1. The C language specifies that main must be used as the main function name; every executable C program must have exactly one main function.
  2. Each executable statement in a C program must end with a semicolon “;”.
  3. Comment content must be placed between the symbols “/” and “/”, and “/” and “/” cannot be nested within comments.

2.2 Identifiers, Constants, and Variables#

2.2.1 Identifiers#

  1. Composed of letters, digits, and underscores, and the first character must be a letter or underscore.
  2. Categories:
    1. Keywords
    2. Predefined identifiers
    3. User-defined identifiers

2.2.2 Constants#

  1. Values that cannot be changed during program execution.
  2. Classification:
    1. Integer constants: represented only by digits, without a decimal point.
      1. Short integer constants
      2. Long integer constants
    2. Real constants: numbers that must include a decimal point.
    3. Character constants
    4. String constants

2.2.3 Symbol Constants#

/* Calculate the area of a circle */
#include "stdio.h"  

#define PI 3.14159 /* Define the symbol name PI as 3.14159 */  

int main() {  
	double r, s;  
	r = 5.0;  
	s = PI * r * r;  
	printf("s=%f\n", s);  
}

2.2.4 Variables#

  1. Variables refer to quantities whose values can change during program execution.

2.3 Integer Data#

2.3.1 Integer Constants#

  1. Integer constants can be represented in decimal, octal, and hexadecimal forms.
  2. Octal numbers: must start with the digit “0”.
  3. Hexadecimal numbers: start with “0x” or “0X”; letters a, b, c, d, e, f in hexadecimal can be either lowercase or uppercase.
  4. In C programs, only decimal numbers can be negative, while octal and hexadecimal numbers can only be integers.

2.3.2 Integer Variables#

  1. Basic integer variables are defined using the type keyword int.
int k;  
int i, j, k;  
int i = 1, j = 0, k = 2;

2.3.3 Classification of Integer Data#

  1. Short integer (short int)
  2. Basic integer (int)
  3. Long integer (long int)
  4. Unsigned: unsigned integers have a letter suffix u or U at the end; if it is a long unsigned integer constant, add the suffix lu or LU.

If a variable is not specified as unsigned, it is implicitly considered signed.

2.3.4 Storage Form of Integers in Memory#

  1. The rightmost bit of a byte is called the least significant bit, and the leftmost bit is called the most significant bit. For a signed integer, the highest bit is used to store the sign of the integer, known as the sign bit. If it is a positive integer, the highest bit is set to 0; if it is a negative integer, the highest bit is set to 1.
  2. Negative integers are stored in memory in "two's complement" form.

To find the two's complement of a binary number, for example, 10000101 (decimal -5), the steps are as follows:

  • Find the one's complement of the original code. Invert the binary code of the original code except for the sign bit, resulting in 11111010.
  • Add 1 to the obtained one's complement to get the two's complement of the original code, resulting in 11111011.

To convert the binary code stored in memory in two's complement form to a negative decimal integer:

  • First, invert all bits except for the sign bit.
  • Convert the obtained binary number to a decimal number.
  • Subtract 1 from the obtained number.

2.4 Real Data#

2.4.1 Real Constants#

  1. Decimal form: must have a decimal point.

2.4.2 Real Variables#

  1. Single precision (float)
    1. Definition: float a,b,c;
    2. Occupies 4 bytes of storage.
  2. Double precision (double)
    1. Definition: double x,y,z;
    2. Occupies 8 bytes of storage.

2.5 Arithmetic Expressions#

2.5.1 Basic Arithmetic Operators#

  1. Addition (+)
  2. Subtraction (-)
  3. Multiplication (*)
  4. Division (/)
  5. Modulus (%): the operation can only be performed on integers.
  • These operators require two operands, known as binary operators;
  • “+” and “-” can also be used as unary operators, and the operator must appear to the left of the operand.
  • If the types of the operands on both sides of a binary operator are the same, the result type will be the same as the operand type.
  • If the types of the operands on both sides of a binary operator are different, the system will automatically perform type conversion to make the types on both sides consistent before performing the operation.
  • In C language, all operations on real numbers are performed in double precision.

2.5.2 Operator Precedence, Associativity, and Arithmetic Expressions#

  1. Precedence of arithmetic operators
    20230805

  2. Associativity of arithmetic operators and parentheses

    1. Among the above operators, only the unary operators “+” and “-” have right-to-left associativity; all other operators have left-to-right associativity.
  3. Arithmetic expressions

    1. Definition: An expression that connects operators (or operands) using arithmetic operators and a pair of parentheses, conforming to C language syntax.
    2. The operands can be constants, variables, and functions, etc.

2.5.3 Explicit Type Conversion Expressions#

  1. Format: (type)(expression)
  2. (type) is called the explicit type conversion operator.

2.6 Assignment Expressions#

2.6.1 Assignment Operator and Assignment Expressions#

  1. Format: variable = expression
  2. The left side of the assignment operator can only be a variable, not a constant or expression.
  3. The C language specifies that the new value obtained in the leftmost variable is the value of the assignment expression.

2.6.2 Compound Assignment Expressions#

  1. Definition: Adding other operators before the assignment operator.

2.6.3 Type Conversion in Assignment Operations#

  1. If the data types on both sides of the assignment operator are inconsistent, the system will automatically convert the value obtained from the right side expression to the type of the variable on the left side before the assignment.
  2. Conversion rules in C language expressions (excluding assignment expressions):
    1. One short integer, one long integer: $short \to long$
    2. One signed integer, one unsigned integer: $signed \to unsigned$

2.7 Increment, Decrement Operators, and Comma#

2.7.1 Increment Operator “++” and Decrement Operator “--”#

  1. “++” and “--” are both unary operators and cannot be assigned to constants or expressions.
  2. They can appear in both prefix and postfix forms.
  3. For variables, increment or decrement by 1; for expressions, the prefix form increments first and then uses the variable value, while the postfix form uses the variable value first and then increments.
  4. Associativity: right to left.

2.7.2 Comma Operator and Comma Expressions#

  1. The associativity of the comma operator: left to right.
  2. The comma operator has the lowest precedence.

Chapter Three Sequential Structure#

3.1 Assignment Statements#

  1. Assignment statements (expression statements): Add a “;” at the end of the assignment expression.

3.2 Data Output#

3.2.1 General Calling Form of printf Function#

  1. Calling form: printf(format control, output item 1, output item 2, ...)
printf("a=%d,b=%d", a, b);

3.2.2 Common Format Specifications in printf Function#

Each format specification must start with “%” and end with a format character, and “width specification”, left alignment symbol “-”, leading zero symbol “0” can be inserted as needed.

  1. Format characters
Format CharacterDescription
cOutputs a character
d or iOutputs a signed decimal integer. %ld for long, %hd for short, %I64d for 64-bit long integer
oOutputs an integer in octal format. %#o adds leading 0
x or XOutputs an integer in hexadecimal format. %#x or %#X outputs hexadecimal numbers with leading 0x or 0X
uOutputs an integer in unsigned decimal format
fOutputs a floating-point number in decimal form (single and double precision)
e or EOutputs a floating-point number in exponential form (single and double precision)
g or GThe system decides whether to use %f or %e (or %E) format to minimize output width
sOutputs a string until encountering “\0”
pOutputs the memory address of a variable
%Outputs a %
  1. Width specification for output data
    1. Insert an integer constant between % and format character to specify the width of the output. If the specified width exceeds the actual width of the output data, it will be right-aligned with spaces on the left.
    2. For float and double type real numbers, the width can be specified in the form of “n1.n2” (where n1 and n2 represent integer constants), where n1 specifies the width of the output data (including the decimal point), and n2 specifies the number of decimal places after the decimal point, n2 is also called precision.
      1. For f, e, or E, if the number of decimal places in the output data exceeds n2, the excess decimals on the right are truncated, and the first truncated decimal is rounded; if the number of decimal places in the output data is less than n2, 0 is added to the rightmost decimal.
      2. The format “.n2” can also be used, not specifying total width; if “n1.0” or “.0” format is specified, the decimal point and decimal part will not be output.
      3. For g or G, the width is used to specify the number of significant digits. The default is 6 significant digits.
  2. Left alignment of output data: Add “-” between “%” and width.
  3. To ensure that the output data always has +/-: Add “+” between “%” and format character.

3.2.3 Precautions When Using printf Function#

  1. When calling the printf function, its parameters are processed from right to left.
  2. The field width of the output data can be changed.
printf("%*d",m,i);    /* Outputs the value of i according to the field width specified by m, without outputting the value of m */

3.3 Data Input#

3.3.1 General Calling Form of scanf Function#

  1. Calling form: scanf(format control, input item 1, input item 2, ...)
scanf("%d%f%lf",&k,&a,&y);

3.3.2 Common Format Specifications in scanf Function#

Format CharacterDescription
cInputs a character
dInputs a signed decimal integer
iInputs an integer, which can be an octal number with leading 0 or a hexadecimal number with leading 0x (or 0X)
oInputs an integer in octal format, can have leading 0 or not
xInputs an integer in hexadecimal format, can have leading 0x or 0X or not
uInputs an integer in unsigned decimal format
f (lf)Inputs a floating-point number in decimal or exponential form (single precision uses f, double precision uses lf)
e (le)Same as above
sInputs a string until encountering “\0”
  1. The return value of the scanf function is the number of correctly input data items for this scanf call.

3.3.3 Inputting Data from the Keyboard via scanf Function#

  1. Input numeric data: When inputting integer or real number data, the input data must be separated by spaces, newline characters, tab characters, etc.
  2. To skip a certain input data: Add “*” between % and character.

3.4 Compound Statements and Empty Statements#

3.4.1 Compound Statements#

  1. Statement form: {statement1 statement2 statement3 ··· statementn}

3.4.2 Empty Statements#

int main(){
	;    /* Empty statement */
}

3.5 Example Program#

/*  
* Created by binxin on 2023/8/6.  
*  
* Input two integers into variables x and y from the terminal; then output x and y; after swapping the values of x and y, output x and y again.  
*/  
#include "stdio.h"  
  
int main() {  
	int x, y, t;  
	printf("Input the values of integers x and y: ");  
	scanf("%d%d", &x, &y);  
	printf("x=%d,y=%d\n", x, y);  
	t = x;  
	x = y;  
	y = t;  
	printf("x=%d,y=%d", x, y);  
}
/*  
* Created by binxin on 2023/8/6.  
*  
* Input a double type number, keep two decimal places, round the third decimal place, and then output this number.  
*/  
#include "stdio.h"  
  
int main() {  
	double x;  
	printf("Input data: ");  
	scanf("%lf", &x);  
	printf("x=%f\n", x);  
	x = x * 100;  
	x = x + 0.5;  
	x = (int) x;  
	x = x / 100;  
	printf("x=%f", x);  
}

Chapter Four Selection Structure#

4.1 Relational and Logical Operations#

4.1.1 Logical Values in C Language#

  1. In C language, non-zero represents "true", and 0 represents "false".

4.1.2 Relational Operators and Relational Expressions#

  1. Six relational operators:
    1. Less than <
    2. Greater than >
    3. Equal to ==
    4. Less than or equal to <=
    5. Greater than or equal to >=
    6. Not equal to !=
  2. Operators composed of two characters must not have spaces between them.
  3. Relational operators are binary operators and have left-to-right associativity.
  4. The value of relational operations is a "logical value", which can only be integer 0 or 1.

4.1.3 Logical Operators and Logical Expressions#

4.1.3.1 Logical Operators in C Language#

  1. Three logical operators:
    1. Logical AND &&
    2. Logical OR ||
    3. Logical NOT !
  2. && and || are binary operators, while ! is a unary operator that appears to the left of the operand. Associativity is left to right.

4.1.3.2 Logical Expressions and Their Values#

  1. The result of a logical expression is either 1 or 0.
  2. Logical expressions composed of && or || may produce a "short-circuit" phenomenon under specific conditions.

4.2 if Statements and Selection Structures Formed with if Statements#

4.2.1 if Statements#

  1. Basic form
if(expression) statement    /* if statement without else clause */

if(expression) statement1    /* if statement with else clause */
else statement2

4.2.2 Nested if Statements#

  1. Statement form
if(expression1){
	if(expression2) statement1
} else {
	statement2
}
  1. The else clause is always associated with the nearest preceding if without an else.

4.3 Selection Structures Formed with Conditional Expressions#

  1. Conditional operator: ? :, the only ternary operator provided by C language.
  2. Conditional expressions formed with the conditional operator: expression1 ? expression2 : expression3.
  3. Operational function: When the value of expression1 is non-zero, the value of expression2 is the value of the entire expression; when the value of expression1 is zero, the value of expression3 is the value of the entire expression.

4.4 switch Statements and Selection Structures Formed with switch Statements and break Statements#

switch(expression){
	case constant expression1: statement1
	case constant expression2: statement2
			·
			·
			·
	case constant expressionn: statementn
	default        : statementn+1
}
  1. There must be a space between the keyword case and the constant expression.
  2. Usually, a break statement is added at the end of the statement after case; whenever the break statement is executed, it immediately exits the switch statement body.

Chapter Five Loop Structure#

5.1 while Statements and Loop Structures Formed with while Statements#

  1. General form: while(expression) loop body
    1. The expression cannot be empty.

5.2 do-while Statements and Loop Structures Formed with do-while Statements#

  1. General form
do
	loop body
while(expression);
  1. do must be used in conjunction with while.

5.3 for Statements and Loop Structures Formed with for Statements#

  1. General form: for(expression1; expression2; expression3) loop body
  2. Execution process
    1. Calculate expression1.
    2. Calculate expression2. If its value is non-zero, go to step 3; if its value is zero, go to step 5.
    3. Execute the for loop body once.
    4. Calculate expression3, go back to step 2.
    5. End the loop.
  3. The expressions in the for statement can be partially or completely omitted, but the two “;” cannot be omitted.

5.4 Nesting of Loop Structures#

  1. Nested loops: A loop body completely contains another loop.

5.5 The Role of break and continue Statements in Loop Bodies#

  1. The break statement can only be used within loop bodies and switch statement bodies.
  2. The continue statement skips the remaining statements in the current loop body and immediately proceeds to the next loop condition check.

5.6 Example Program#

/*
Select the maximum value from a number of positive integers inputted, ending input with -1.
*/
#include <stdio.h>
  
int main(){
    int max, n;
    do{
        printf("Input data, end input with -1: ");
        scanf("%d", &n);
        if(max < n){
            max = n;
        }
    } while (n != -1);
    printf("max=%d", max);
}
/*
Use the iterative method to find the square root of a number a. The known iterative formula for finding the square root is x1 = (x0 + a/x0) / 2.
*/
#include <stdio.h>
#include <math.h>

int main(){
    double x0, x1, a;
    printf("Input data: ");
    scanf("%lf", &a);
    x0 = a / 2;
    x1 = (x0 + a / x0) / 2;
    do{
        x0 = x1;
        x1 = (x0 + a / x0) / 2;
    } while (a > 0 && fabs(x1 - x0) > 1e-6);
    printf("x=%f", x1);
}

Chapter Six Character Data#

6.1 Character Constants#

6.1.1 Character Constants#

  1. Uppercase and lowercase letters in single quotes represent different character constants.
  2. A space character in single quotes is also a character constant.
  3. Character constants can only contain one character.
  4. Character constants can only be enclosed in single quotes, not double quotes.
  5. Character constants occupy one byte in memory, storing the ASCII code value of the character.

6.1.2 Escape Character Constants#

Character FormFunction
\nCarriage return and newline
\tHorizontal tab
\vVertical tab
\rCarriage return
\fForm feed
\bBackspace character
\Backslash character “\”
'Single quote character
"Double quote character
\dddAn ASCII character represented by a three-digit octal number
\xhhAn ASCII character represented by a two-digit hexadecimal number
\0Null value, its ASCII code value is 0
  1. Escape character constants represent only one character.
  2. The octal number after the backslash can be without a leading 0.
  3. Within a pair of single quotes, an ASCII character can be represented by a backslash followed by a hexadecimal number.

6.1.3 String Constants#

  1. Definition: A string of characters enclosed in double quotes.
  2. In C language, the system automatically adds a character '\0' at the end of each string as a termination flag.

6.1.4 Operations on Character Constants#

  1. Character constants can participate in any integer operations.

6.2 Character Variables#

  1. In C language, character variables are defined using the keyword char, and can be initialized at the same time.
  2. Occupies one byte.
  3. Character variables can be treated as integer variables and can participate in any operations allowed on integer variables.

6.3 Input and Output of Characters#

6.3.1 Calling printf and scanf Functions to Output and Input Characters#

  1. When calling functions for input and output, the command line including the header file stdio.h must appear at the beginning of the program: #include <stdio.h>

6.3.2 Calling putchar and getchar Functions to Output and Input Characters#

  1. The putchar function is used to output characters, calling form: putchar(ch)
    1. ch can be a character constant or a character variable.
  2. The getchar function is used to input characters, calling form: ch=getchar()

6.4 Example Program#

/*
Output 26 uppercase letters and their ASCII codes, outputting two sets of data per line.
*/
#include <stdio.h>

int main(){
    char c = 'A';
    for (int i = 0; i < 26; i=i+2){
        printf("%c %d %c %d\n", c + i, c + i, c + i + 1, c + i + 1);
    }
}
/*
Input a character from the terminal, and the program will continue only when the Enter key is pressed.
*/
#include <stdio.h>

int main(){
    printf("Input data: ");
    while (getchar() != '\n'){
        
    }
    printf("end");
}
/*
Convert all lowercase letters in a line of characters input from the terminal to uppercase letters, leaving other characters unchanged.
*/
#include <stdio.h>

int main(){
    char ch;
    printf("Input data: ");
    while ((ch = getchar()) != '\n'){
        if(ch >= 'a' && ch <= 'z'){
            ch = ch - 'a' + 'A';
        }
        putchar(ch);
    }
}
/*
Count the number of space characters, newline characters, and horizontal tab characters in the input, ending input with '!' 
*/
#include <stdio.h>

int main(){
    char ch;
    int sum = 0;
    printf("Input data: ");
    while ((ch = getchar()) != '!'){
        if(ch == ' ' || ch == '\n' || ch == '\t'){
            sum++;
        }
    }
    printf("sum=%d", sum);
}
/*
Translate a string of ciphertext into plaintext, ending with the character '@'. The decoding rules are as follows:
(1) If it is a letter, convert it to the next letter in the letter sequence. For example, A becomes B.
(2) If it is the letter Z, it becomes A.
(3) Both uppercase and lowercase letters are converted to lowercase letters.
(4) Other characters are translated as they are.
*/
#include <stdio.h>
#include <ctype.h>

int main(){
    char ch;
    printf("Input data: ");
    while ((ch = getchar()) != '@'){
        if(isalpha(ch)){    /* isalpha(ch) checks if the character in ch is a letter; if so, the function returns 1 */
            ch = tolower(ch);   /* Convert uppercase letters to lowercase letters */
            ch = (ch - 'a' + 1) % 26 + 'a';
        }
        putchar(ch);
    }
}

Chapter Seven Functions#

7.1 Library Functions#

  1. The include command line required when calling C language library functions.
  2. The general form of calling standard library functions: function name(parameter list).

7.2 Function Definition and Return Values#

7.2.1 Syntax of Function Definition#

  1. General form of function definition
return type function name(type formal parameter1, type formal parameter2, ...){
	Declaration part
	Statement part
}
  1. Function names and formal parameters are identifiers named by the user. In the same program, function names must be unique, and formal parameter names only need to be unique within the same function.
  2. Functions cannot be defined inside other functions.
  3. The default return type of a function is int.
  4. Functions must be defined (or declared) before being called, except for functions with return types of int or char.
  5. If a function is only used to perform certain operations without returning a value, it must be defined as void type.

7.2.2 Function Return Values#

  1. The value of a function is returned through the return statement, general form: return expression; or return (expression).
  2. Within the same function, the return statement can only be executed once.

7.3 Function Calls#

7.3.1 Two Ways to Call Functions#

  1. General calling form of a function: function name(actual parameter list).
  2. Two calling methods:
    1. When the called function is used to obtain a value, the function call can appear in any place where an expression is allowed.
    2. When the function does not need to return a value, the function call can appear as an independent statement.

7.3.2 Syntax Requirements for Function Calls#

  1. When calling a function, the function name must exactly match the name of the called function.
  2. The number of actual parameters must match the number of formal parameters.
  3. The function must be defined before being called (except for functions with return types of int or char).
  4. A function can call itself directly or indirectly, which is called recursive calling.

7.4 Function Declarations#

7.4.1 Form of Function Declaration#

  1. Except for the main function, user-defined functions follow the rule of "define first, use later".
  2. General form:
    1. type name(parameter type1, parameter type2, ...)
    2. type name(parameter type1 parameter name1, parameter type2 parameter name2, ...)

7.4.2 Location of Function Declarations#

  1. When declaring a function outside of all functions, it can be called at any position after the declaration.
  2. Function declarations can also be placed in the declaration part within the calling function; if declared within the main function, the function can only be recognized within the main function.

7.5 Data Passing Between Calling Functions and Called Functions#

  1. Data passing between actual parameters and formal parameters.
  2. Return values of functions are returned to the calling function through the return statement.
  3. Through global variables (not recommended).

7.6 Example Program#

/*
Write a function isprime(int a) to determine whether the variable a is a prime number. If it is a prime number, return 1; otherwise, return 0.
*/
#include <stdio.h>
int isprime(int a);

int main(){
    int x;
    printf("Input data: ");
    scanf("%d", &x);
    if(isprime(x)){
        printf("Prime number");
    } else{
        printf("Not a prime number");
    }
}

int isprime(int a){
    for (int i = 2; i <= a / 2; i++){
        if (a % i == 0){
            return 0;
        }
    }
    return 1;
}

Chapter Eight Addresses and Pointers#

8.1 Definition of Pointer Variables and Base Types of Pointer Variables#

  1. General form of defining pointer variables: type *pointer variable name1, *pointer variable name2, ....
  2. Pointer variables must distinguish base types; pointer variables of different base types cannot be mixed.

8.2 Assigning Values to Pointer Variables#

8.2.1 Assigning Address Values to Pointer Variables#

  1. Obtain address values using the address operator (&).
    1. The address operator can only be applied to variables and array elements, not to expressions, constants, or variables declared as register.
    2. & must be placed to the left of the operand, and the type of the operand must match the base type of the pointer variable.
  2. Obtain address values through pointer variables.
    1. When performing assignment operations, the base types of the pointer variables on both sides of the assignment must be the same.
  3. Obtain address values through standard functions.
    1. You can use library functions malloc and calloc to allocate dynamic storage units in memory and assign the addresses of the allocated dynamic storage units to pointer variables.

8.2.2 Assigning "Null" Values to Pointer Variables#

  1. p=NULL
  2. Pointer p does not point to a storage unit with address 0, but has a definite value - "null".

8.3 Operations on Pointer Variables#

8.3.1 Referencing a Storage Unit via a Pointer#

  1. Indirect access operator (dereference operator): *
    1. When a pointer variable stores a specific address value, you can use “*” to reference the storage unit at that address.
    2. It is a unary operator and must appear to the left of the operand.

8.3.2 Moving Pointers#

  1. Definition: Adding or subtracting an integer from a pointer variable, or assigning a value to make the pointer variable point to adjacent storage units.
  2. Pointer movement is meaningful only when the pointer points to a series of contiguous storage units.

8.4 Passing Address Values Between Functions#

8.4.1 Data Passing Between Actual Parameters and Formal Parameters When the Formal Parameter is a Pointer Variable#

/*
Write a function myadd(int *a,int *b) that adds the two values pointed to by pointers a and b, and returns the sum as the function value.
*/
#include <stdio.h>
int myadd(int *a, int *b);

int main(){
    int a, b, sum;
    printf("Input data: ");
    scanf("%d%d", &a, &b);
    sum = myadd(&a, &b);
    printf("sum=%d", sum);
}

int myadd(int *a, int *b){
    int sum;
    sum = *a + *b;
    return sum;
}

8.4.2 Directly Changing the Value of Variables in the Calling Function by Passing Addresses in the Called Function#

/*
Call the swap function to exchange the data in variables x and y in the main function.
*/
#include <stdio.h>
void swap(int *, int *);

int main(){
    int a = 30, b = 20;
    printf("a=%d b=%d\n", a, b);
    swap(&a, &b);
    printf("a=%d b=%d", a, b);
}

void swap(int *a, int *b){
    int t;
    t = *a;
    *a = *b;
    *b = t;
}

8.4.3 Returning Address Values from Functions#

/*
Return the address of the larger number stored in variables i and j in the main function as the function value.
*/
#include <stdio.h>
int *fun(int *, int *);

int main(){
    int i, j;
    i = 10;
    j = 20;
    printf("max=%d", *fun(&i, &j));
}

int *fun(int *i, int *j){
    if(*i > *j){
        return i;
    } else {
        return j;
    }
}

Chapter Nine Arrays#

9.1 Definition of One-Dimensional Arrays and Referencing One-Dimensional Array Elements#

9.1.1 Definition of One-Dimensional Arrays#

  1. Definition: Each element in the array has only one subscript.
  2. General form: type array name[integer constant expression], ...
  3. Array specifiers and ordinary variable names can appear simultaneously in a type definition statement.

9.1.2 Referencing One-Dimensional Arrays#

  1. Reference form: array name[subscript expression]

9.1.3 Initialization of One-Dimensional Arrays#

  1. When the number of initial values is less than the number of defined array elements, the remaining elements will automatically be initialized to 0.
  2. For character arrays, the same applies, with the remaining elements initialized to 0, i.e., \0.

9.1.4 Defining Array Size by Assigning Initial Values#

  1. The C language allows defining the size of an array by assigning initial values; in this case, the size of the array can be omitted in the pair of brackets.

9.1.5 Example of Defining One-Dimensional Arrays and Referencing Array Elements#

/*
Define an int type array with 30 elements, assign odd numbers 1, 3, 5, ..., to the array elements, and then output them in order, 10 numbers per line, and finally output them in reverse order, 10 numbers per line.
*/
#include <stdio.h>

int main(){
    int a[30];
    int i, k = 1;
    for (i = 0; i < 30; i++){
        a[i] = k;
        k = k + 2;
    }
    for (i = 0; i < 30; i++){
        printf("%4d", a[i]);
        if ((i + 1) % 10 == 0){
            printf("\n");
        }
    }
    printf("\n");
    for (i = 29; i >= 0; i--){
        printf("%4d", a[i]);
        if (i % 10 == 0){
            printf("\n");
        }
    }
}

9.2 One-Dimensional Arrays and Pointers#

  1. The array name defined in the function body or outside the function can be considered as a pointer variable name that stores address values, where the address value is the address of the first element of the array, which is the starting address of the contiguous storage units occupied by the array; the type of the array during definition is the base type of this pointer variable.
    1. The address value in this pointer variable cannot be changed, i.e., the array name cannot be reassigned.
  2. You can add an integer to the array name to sequentially express the addresses of different elements in the array.

9.3 Referencing One-Dimensional Arrays and Array Elements Between Functions#

9.3.1 Array Elements as Actual Parameters#

  1. Each array element actually represents a storage unit in memory, and the value of the array element can be passed to the variable; in the function, you can only operate on that variable, not directly reference the corresponding array element, and it is not possible to change the value in the corresponding array element in the function.

9.3.2 Array Name as Actual Parameters#

  1. The array name itself is an address value, and the corresponding formal parameter should be a pointer variable, which must have the same base type as the array. In the function, you can reference the corresponding array elements in the calling function through this pointer variable, thus allowing operations on the corresponding array elements in the calling function to change their values.
/*
Input several integers greater than or equal to 0 into the array defined in the main function, using a negative number as the input end flag; call another function to output the data in the array.
*/
#include <stdio.h>
#define M 100
int input(int *a);
void output(int *a, int n);

int main(){
    int a[M], n;
    n = input(a);
    output(a, n);
}

int input(int *a){
    int n, i;
    i = 0;
    printf("Input data: ");
    scanf("%d", &n);
    while (n >= 0){
        a[i] = n;
        i++;
        scanf("%d", &n);
    }
    return i - 1;
}

void output(int *a, int n){
    for (int i = 0; i <= n; i++){
        printf("%d ", a[i]);
    }
}

9.3.3 Address of Array Elements as Actual Parameters#

  1. When using array elements as actual parameters, because they are address values, the corresponding formal parameters should also be pointer variables of the same base type.
/*
For a char type array with 10 elements, set all elements starting from index 4 to asterisks, keeping the first four elements unchanged.
*/
#include <stdio.h>
#define M 10
#define B 4
void setstar(char *c);

int main(){
    char c[M] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'};
    setstar(c);
    for (int i = 0; i < M; i++){
        printf("%c ", c[i]);
    }
}

void setstar(char *c){
    for (int i = B; i < M; i++){
        c[i] = '*';
    }
}

9.4 Example of One-Dimensional Array Applications#

/*
Define an array with 15 elements and write functions to complete the following operations:
1. Use the random function in the C library to assign random numbers between 0 and 49 to all elements.
2. Output the values of the array elements.
3. Calculate the sum of every three numbers in order and return it to the main function.
4. Finally, output all the calculated sums.
*/
#include <stdio.h>
#include <stdlib.h>
#define M 15
#define N 3

void getrand(int *a);
void arrout(int *a, int n);
void getsum(int *a, int n, int *sum);

int main(){
    int a[M], sum[M/N];
    getrand(a);
    arrout(a, M);
    getsum(a, N, sum);
    arrout(sum, M/N);
}

void getrand(int *a){
    for (int i = 0; i < M; i++){
        a[i] = rand() % 50;
    }
}

void arrout(int *a, int n){
    for (int i = 0; i < n; i++){
        printf("%d ", a[i]);
    }
    printf("\n");
}

void getsum(int *a, int n, int *sum){
    for (int i = 0; i < M/N; i++){
        sum[i] = a[i * N] + a[i * N + 1] + a[i * N + 2];
    }
}

9.5 Definition of Two-Dimensional Arrays and Referencing Two-Dimensional Array Elements#

9.5.1 Definition of Two-Dimensional Arrays#

  1. Definition statement form: type array name[constant expression1][constant expression2], ....

9.5.2 Referencing Two-Dimensional Arrays#

  1. Reference form: array name[subscript expression1][subscript expression2].

9.5.3 Initialization of Two-Dimensional Arrays#

  1. The number of initial values must match the number of array elements.
    1. You can assign initial values to the elements of a two-dimensional array while defining it: int a[4][3]={{1,2,3},{4,5,6},{7,8,9},{10,11,12}};.
  2. If the number of initial values in each row is different from the number of array elements, the system will automatically assign values to the remaining elements.
  3. If the number of initial value rows is less than the number of array rows, the system will automatically assign initial values of 0 to the elements of the remaining rows.
  4. When assigning initial values, you can omit the braces.
    1. int a[4,3]={1,2,4,5};
      1. The system will assign the data in the braces to the elements in the order they are arranged in memory; if the data is insufficient, the system will automatically assign initial values of 0 to the remaining elements.

9.5.4 Defining the Size of a Two-Dimensional Array by Assigning Initial Values#

  1. You can only omit the constant expression in the first pair of brackets, but not in the second pair.

9.5.5 Example of Defining Two-Dimensional Arrays and Referencing Array Elements#

/*
Input data for a 2*3 two-dimensional array from the keyboard, assigning 1, 2, 3 to the first row and 10, 20, 30 to the second row, and then output this two-dimensional array by row.
*/
#include <stdio.h>

int main(){
    int a[2][3];
    printf("Input data: ");
    for (int i = 0; i < 2; i++){
        for (int j = 0; j < 3; j++){
            scanf("%d", &a[i][j]);
        }
    }
    for (int i = 0; i < 2; i++){
        for (int j = 0; j < 3; j++){
            printf("%4d", a[i][j]);
        }
        printf("\n");
    }
}

9.6 Two-Dimensional Arrays and Pointer Arrays as Actual Parameters#

9.6.1 Data Passing Between Actual Parameters and Formal Parameters When the Actual Parameter is a Two-Dimensional Array Name#

  1. When the two-dimensional array name is used as an actual parameter, the corresponding formal parameter must be a row pointer variable.

9.6.2 Data Passing Between Actual Parameters and Formal Parameters When the Actual Parameter is a Pointer Array#

  1. When a pointer array is used as an actual parameter, the corresponding formal parameter should be a pointer to a pointer.

9.7 Example of Two-Dimensional Array Program#

/*
Assign integers between 10 and 40 to the elements of a 5*6 two-dimensional array using the random function, and calculate the average value of the elements in each row of the two-dimensional array.
*/
#include <stdio.h>
#include <stdlib.h>
void getrand(int a[][6]);
void getave(int a[][6], double *ave);

int main(){
    int a[5][6];
    double ave[5] = {0};
    getrand(a);
    for (int i = 0; i < 5; i++){
        for (int j = 0; j < 6; j++){
            printf("%d ", a[i][j]);
        }
        printf("\n");
    }
    getave(a, ave);
    for (int i = 0; i < 5; i++){
        printf("%f ", ave[i]);
    }
}

void getrand(int a[][6]){
    for (int i = 0; i < 5; i++){
        for (int j = 0; j < 6; j++){
            a[i][j] = rand() % 31 + 10;
        }
    }
}

void getave(int a[][6], double *ave){
    for (int i = 0; i < 5; i++){
        for (int j = 0; j < 6; j++){
            ave[i] = ave[i] + a[i][j];
        }
        ave[i] = ave[i] / 6;
    }
}

Chapter Ten Strings#

10.1 Using One-Dimensional Character Arrays to Store Strings#

  1. The convention for strings in C language:
    1. Strings are stored using one-dimensional character arrays, and \0 is used as the "string termination flag".
    2. \0 occupies storage space but is not counted in the actual length of the string.
  2. The convention for representing string constants in C language:
    1. String constants are a string of characters enclosed in double quotes, and the system automatically adds the character \0 at the end.
  3. String constants in C language provide address values.
  4. The difference between character arrays and strings:
    1. Strings can only be stored in character arrays; you cannot directly assign string constants or strings from other character arrays to string variables using assignment statements.
    2. Strings are a specific application of character arrays.

10.1.1 Assigning Strings to One-Dimensional Character Arrays by Initial Values#

  1. Assign initial values to one-dimensional character arrays in the same way as assigning to ordinary arrays.
    1. When the number of assigned initial values is less than the number of elements in the array, the system will automatically add \0 to the remaining elements.
  2. Directly assign string constants during initialization.

10.1.2 Assigning Strings to One-Dimensional Character Arrays During Program Execution#

  1. You cannot assign a string to a character array as a whole using an assignment statement.
  2. You can assign character values to array elements one by one, and finally manually add the string termination flag.

10.2 Making Pointers Point to a String#

  1. Making a pointer point to a string by assigning initial values:
    1. You can assign the starting address of the storage unit storing the string to the character pointer variable while defining it.
  2. Making a pointer point to a string through assignment operations.

10.3 Input and Output of Strings#

10.3.1 Necessary Conditions for Inputting and Outputting Strings#

  1. When outputting strings, the output items can be string constants or character array names, or character pointer variables pointing to strings.
  2. When inputting strings, the input items can be character array names or character pointer variables.

10.3.2 Using Format Specifier %s for Whole String Input and Output#

  1. Using scanf function allows for whole string input.
    1. Spaces and newline characters serve as delimiters for input data and cannot be read.
    2. If the length of the input string exceeds the number of characters that the character array can hold, the system does not report an error. It is equivalent to an out-of-bounds index.
    3. When the input item is the address of an array element, the input characters will be stored in that array starting from this element.
    4. When the input item is a character pointer variable, this pointer variable must point to a determined contiguous storage unit with sufficient space.
  2. Using printf function allows for whole string output.
    1. It outputs the characters in the storage unit until encountering the first \0.
    2. \0 is the termination flag and is not included in the output characters.
    3. After outputting, it does not automatically add a newline.

10.3.3 Calling gets and puts Functions to Input or Output a Line of String#

  1. gets function: gets(str_adr)
    1. The gets function reads a string from the terminal keyboard (including spaces) until it reads a newline character.
    2. The newline character is not included in the string content; the system automatically replaces it with \0.
  2. puts function: puts(str_adr)
    1. It outputs the characters in the storage unit sequentially until encountering the first \0, and automatically outputs a newline.

10.4 Functions for String Processing#

When using the following functions, include the header file <string.h>.

  1. String assignment (copy) function strcpy: strcpy(s1, s2)
    1. Copies the content of the string pointed to by s2 (source) into the storage space pointed to by s1 (destination), and the function returns the value of s1, which is the address of the destination string.
    2. s1 must point to a storage space that can accommodate the string s2.
  2. String concatenation function strcat: strcat(s1, s2)
    1. Concatenates the content of the string pointed to by s2 to the end of the string pointed to by s1, automatically overwriting the \0 at the end of s1, and the function returns the address value pointed to by s1.
    2. The string pointed to by s1 should have enough space to accommodate the combined content of both strings.
  3. Function to calculate string length strlen: strlen(s)
    1. Calculates the length of the string starting at address s and returns it as the function value. The termination flag \0 is not included in the string length.
  4. String comparison function strcmp: strcmp(s1, s2)
    1. Compares the corresponding characters in s1 and s2 one by one; the character size is based on their ASCII code values.

10.5 Example Program#

/*
Write a function length(char *s) that returns the length of the string pointed to by pointer s, equivalent to the functionality of the library function strlen.
*/
#include <stdio.h>
int length(char *s);

int main(){
    int len;
    char str[] = "ABCDEFG";
    len = length(str);
    printf("%d", len);
}

int length(char *s){
    int i = 0;
    while (*(s + i) != '\0'){
        i++;
    }
    return i;
}

Chapter Eleven Further Discussion on Functions#

11.1 Parameters Passed to the main Function#

  1. The main function can typically use two parameters:
    1. The first parameter argc must be an integer.
    2. The second parameter argv is a pointer to an array of character pointers, where each pointer points to a string.
main(int argc, char **argv){
	···
}

11.2 Passing Function Names or Pointers to Functions as Parameters#

  1. Definition of pointer variables pointing to functions: In C language, function names represent the entry address of the function, so you can define a pointer to a function to store this address.
#include <stdio.h>
double fun(int a, int *p){
	···
}
main(){
	double (*fp)(int, int *), y;
	int n;
	fp = fun;
		·
		·
		·
	y = (*fp)(56, &n);    /* Here, the fun function is called through the pointer to the function */
		·
		·
		·
}
  1. Function names or pointers to functions can be passed as parameters to functions.

11.3 Recursive Function Calls#

/*
Use recursion to calculate n!
*/
#include <stdio.h>
int fac(int n);

int main(){
    int n;
    printf("Input data: ");
    scanf("%d", &n);
    printf("%d!=%d", n, fac(n));
}

int fac(int n){
    int f;
    if (n == 1 || n == 0){
        return 1;
    } else {
        f = n * fac(n - 1);
        return f;
    }
}

Chapter Twelve Scope and Storage Classes of User Identifiers in C Language#

12.1 Local Variables#

  1. Local variables (internal variables): Variables defined inside functions or compound statements.
    1. Function parameters also belong to local variables.
  2. Global variables (external variables): Variables defined outside functions.
  3. In C language, there are two storage classes: automatic and static. Local variables can be defined as either automatic or static; local variables can only be static.
    1. Four specifiers related to the two storage classes: auto (automatic), register (register), static (static), extern (external). They can be placed on the left or right of the type name.
    2. The dynamic storage area is used to save the return address of function calls, automatic local variables, etc. The static storage area is used to store local variables and static local variables.

12.2 Local Variables and Their Scope and Lifetime#

12.2.1 auto Variables#

  1. When defining variables inside a function or compound statement, if no storage class is specified, or the auto specifier is used, the system considers the defined variables to have automatic storage class.
  2. The storage unit of auto variables is allocated in the dynamic storage area of memory. Each time the function body (or compound statement) is entered, the system automatically allocates storage units for auto variables; when exiting, these storage units are automatically released for other uses.

12.2.2 register Variables#

  1. Register variables are also automatic class variables. The difference from auto variables is that variables specified with register suggest to the compiler to keep the variable's value in the CPU register instead of occupying a storage unit like ordinary variables.
  2. The number of registers in the CPU is limited, so only a few register variables can be specified.
  3. Register variables do not have addresses and cannot be subjected to address operations.
  4. The declaration of register variables should be as close as possible to their usage, and they should be released as soon as they are no longer needed.

12.2.3 Static Storage Class Local Variables#

  1. When using static to declare a variable inside a function (or compound function), the variable is called a static local variable.
  2. During the execution of the program, static local variables occupy permanent storage units in the static storage area of memory.
  3. The initial value of static local variables is assigned at compile time, not during program execution. For static local variables that are not assigned initial values, the C compiler automatically assigns them an initial value of 0.

12.3 Global Variables and Their Scope and Lifetime#

Global variables have only one static class. For global variables, the extern and static specifiers can be used.

12.3.1 Scope and Lifetime of Global Variables#

  1. Global variables are defined at any position outside functions, and their scope starts from the position of variable definition to the end of the entire source file.
  2. The lifetime of global variables is the entire duration of the program's execution.
  3. If a global variable has the same name as a local variable in a certain function, the global variable will be shadowed in that function.

12.3.2 Using extern to Extend the Scope of Global Variables Within the Same Compilation Unit#

  1. When a global variable is defined later and the function referencing it is defined earlier, the function should use extern to declare the global variable: this variable is a global variable defined externally, which has already been allocated storage units and does not need to allocate additional storage units.

12.3.3 Using extern to Extend the Scope of Global Variables Across Different Compilation Units#

  1. Define all global variables in one file, and use extern to declare these variables in other files that use them.

12.3.4 Static Global Variables#

  1. Static global variables are limited to use within the current compilation unit and cannot be referenced by other compilation units.

12.4 Storage Classes of Functions#

12.4.1 Using extern to Declare Functions#

  1. If the extern specifier is added before the return type of a function, the function is called an "external" function.
  2. The extern specifier can be omitted; generally, functions are implicitly declared as extern.
  3. The characteristic of external functions is that they can be called by functions in other compilation units.

12.4.2 Using static to Declare Functions#

  1. If the static specifier is added before the return type of a function, the function is called a "static" function.
  2. The characteristic of static functions is that they can only be called by other functions within the same compilation unit, and functions in other compilation units are not allowed to call them.

Chapter Thirteen Compilation Preprocessing and Dynamic Storage Allocation#

13.1 Compilation Preprocessing#

In C language, any line starting with “#” is called a "compilation preprocessing" command line.

13.1.1 Macro Replacement#

  1. Non-parameterized macro definitions
    1. Command line form
    #define macro name replacement text
    
    #define macro name
    
    1. The replacement text can include previously defined macro names.
    2. If a macro definition cannot fit in one line, simply add a backslash “\” after the last character.
      1. If there are many spaces before the “\” or at the beginning of the next line, these spaces will also be included in the macro replacement.
    3. The same macro name cannot be defined multiple times unless the two macro definition command lines are exactly the same.
    4. Replacement text cannot replace strings that are the same as macro names within double quotes.
    5. Replacement text does not replace components in user identifiers.
    6. Identifiers used as macro names are usually represented in uppercase letters.
    7. The definition of macro definitions is generally written at the beginning of the program.
  2. Parameterized macro definitions
    1. Command line form: #define macro name(parameter list) replacement text
    2. The same macro name cannot be defined multiple times unless the two macro definition command lines are exactly the same.
    3. When calling a parameterized macro name, a pair of parentheses is essential, and the number of actual parameters in the parentheses should match the number of formal parameters; if there are multiple parameters, they should be separated by commas.
    4. In the "replacement text", the formal parameters and the entire expression should be enclosed in parentheses.
    5. There are no type requirements for parameters in macro replacements.
    6. In macro replacements, actual parameters cannot replace formal parameters enclosed in double quotes.
  3. Terminating macro definitions
    1. You can use #undef to terminate the scope of macro definitions in advance.
    #define PI 3.14
    main(){
    	·
    	·
    	·
    #undef PI
    	·
    	·
    	·
    }
    

13.1.2 File Inclusion#

  1. General form: #include <filename> or #include "filename".

13.2 Dynamic Storage Allocation#

13.2.1 malloc and free Functions#

malloc Function#

  1. The return type of the malloc function is void *, and the calling form of the function is malloc(size), requiring the type of size to be unsigned int.
  2. The malloc function is used to allocate size bytes of storage space and returns a pointer to the starting address of the storage space with a base type of void. If there is not enough memory available for allocation, the function returns NULL.
  3. When dynamically allocating storage space, if the number of bytes occupied by the data type cannot be determined, you can use the sizeof operator to find it: pi = (int *)malloc(sizeof(int));.

free Function#

  1. The calling form of the function: free(p);.
  2. The pointer variable p must point to an address allocated by the dynamic allocation functions malloc or calloc.
  3. The free function releases the storage space pointed to by pointer p.
  4. This function does not return a value.

13.2.2 calloc Function#

  1. The return type of the function is void *.
  2. Calling form: calloc(n, size);, requiring both n and size to be of type unsigned int.
  3. The calloc function is used to allocate contiguous storage space for n data items of the same type, with each data item having a length of size bytes. If the allocation is successful, the function returns the starting address of the storage space; otherwise, it returns NULL.
  4. The storage units allocated through the calloc function are automatically initialized to 0 by the system.

Chapter Fourteen Structures, Unions, and User-Defined Types#

14.1 Using typedef to Define a New Type Name#

  1. General form: typedef type name;.
  2. "Type name" must be a type identifier that has already been defined before this statement.
  3. "Identifier" is a user-defined identifier used as a new type name.
  4. The purpose of the typedef statement is merely to use "identifier" to represent an already existing "type name"; it does not create a new data type, and the original type name remains valid.

14.2 Structure Types#

14.2.1 Structure Type Declaration#

  1. General form
struct structure identifier{
	type name1 member list;
	type name2 member list;
		·
		·
		·
	type nameN member list;
};
  1. struct is a keyword and is the identifier of the structure type.
  2. "Structure identifier" and "structure member name" are both user-defined identifiers; the "structure identifier" is optional and can be omitted in the declaration.
  3. Each "structure member list" can contain multiple members of the same type, separated by commas.
  4. Member names in structures can have the same name as other variables in the program; members in different structures can also have the same name.
  5. The "type name1" to "type nameN" in the structure type declaration can be simple data types, constructed types, or certain structure types.
  6. The ANSI C standard specifies that structures can be nested at least 15 levels deep, and it allows the names of embedded structure members to be the same as those of outer members.

14.2.2 Definition of Structure Type Variables, Arrays, and Pointer Variables#

  1. Define immediately after the structure type declaration.
    1. std can only store 1 set of data; pers can store 3 sets; pstd can point to storage units of struct student type, but currently does not point to anything specific.
struct student{
	char name[12];
	char sex;
	struct data birthday;
	float sc[4];
} std, pers[3], *pstd;
  1. Define a nameless structure type while defining it directly.
struct{
	···
} std, pers[3], *pstd;
  1. Declare the structure type first, then define the variables separately.
    1. This definition method cannot use struct without writing the structure identifier student.
struct student{
	···
};
struct student std, pers[3], *pstd;
  1. Use typedef to define a structure type name, then define variables using the new type name.
typedef struct{
	char name[12];
	char sex;
	struct data birthday;
	float sc[4];
} STREC;
STREC std, pers[4], *pstd;

14.2.3 Assigning Initial Values to Structure Variables and Arrays#

  1. Assign initial values to structure variables: the assigned initial values are placed in a pair of braces.
    1. You cannot skip earlier members to assign values to later members; you can only assign initial values to some of the earlier members, and the system will automatically assign initial values of zero to the remaining unassigned members.
struct student{
	char name[12];
	char sex;
	struct data birthday;
	float sc[4];
} std={"Li Ming",'M',1962,5,10,88,76,86.5,90};
  1. Assign initial values to structure arrays: usually, the values of their members are placed in a pair of braces in order.
struct bookcard{
	char num[5];
	float money;
} bk[3]={{"No.1",35.5},{"No.2",25.0},{"No.3",66.7}};

14.2.4 Referencing Data in Structure Variables#

Referencing Members of Structure Variables#

  1. Reference form
    1. structure variable name.member name
    2. pointer variable name->member name
    3. (*pointer variable name).member name
  2. “.” is called the member operator; “->” is called the structure pointer operator, with no spaces in between.
  3. When accessing members of an embedded structure within a structure variable, you must use member names layer by layer.

Overall Assignment Between Structure Variables of the Same Type#

  1. The ANSI C standard allows overall assignment between structure variables of the same type.

14.2.5 Data Passing of Structure Variables Between Functions#

  1. Passing data of individual members of structure variables to functions.
  2. Passing data of entire structure variables to functions.
  3. Passing the addresses of structure variables to functions.
  4. Passing the names of structure arrays to functions.
  5. Functions returning values of structure types.
  6. Functions returning values of pointer types pointing to structure variables.

14.2.6 Using Structure Variables to Form Linked Lists#

  1. Structures containing pointer members that can point to the structure itself.
/*
A simple linked list
*/
#include <stdio.h>

struct node{
    int data;
    struct node *next;
};
typedef struct node NODETYPE;

int main(){
    NODETYPE a, b, c, *h, *p;
    a.data = 10;
    b.data = 20;
    c.data = 30;    /* Assign values to the data fields in the variables */
    h = &a; /* Connect the nodes */
    a.next = &b;
    b.next = &c;
    c.next = NULL;
    p = h;
    while(p){   /* Move p to point to a, b, c in turn, outputting their data field values */
        printf("%d\n", p->data);
        p = p->next;    /* Move p forward */
    }
}
  1. Singly linked list
    1. Each node should consist of two members: one integer member and one pointer member pointing to the structure itself.

14.3 Unions#

Members in structure variables occupy their own storage space, while members in union variables occupy the same storage space.

14.3.1 Union Type Declaration and Variable Definition#

  1. General form
union union identifier{
	type name1 union member name1;
	type name2 union member name2;
		·
		·
		·
	type nameN union member nameN;
}
  1. union is a keyword and is the identifier of the union type.
  2. The union identifier is optional and can be omitted in the declaration.
  3. Union members can be simple variables, arrays, pointers, structures, and unions (structure members can also be unions).
  4. The definition of union variables is similar to that of structure variables.

(1) When defining a union variable, it can only be initialized with the value of the first member's type.
(2) Since all members in a union variable share storage space, the addresses of all members are the same, and the address of the variable is also the address of that member variable.

14.3.2 Referencing Members of Union Variables#

  1. Referencing members in union variables
    1. General form
    union variable name.member name
    pointer variable name->member name
    (*pointer variable name).member name
    
    1. The value that takes effect in a union variable is the value of the most recently stored member variable; the values of previous member variables will be overwritten.
  2. Overall assignment of union variables
    1. The ANSI C standard allows assignment operations between two union variables of the same type.
  3. Passing union variables as values to functions
    1. Union type variables can be passed as actual parameters, and the addresses of union variables can also be passed.

Chapter Fifteen Bit Operations#

15.1 Bit Operators#

  1. Only ~ is a unary operator; all others are binary operators.
OperatorMeaningPrecedence
~Bitwise NOT1 (high)
<<Left Shift2
>>Right Shift2
&Bitwise AND3
^Bitwise XOR4
Bitwise OR

15.2 Functionality of Bit Operators#

"Bitwise NOT" Operation#

  1. Inverts the content of the operand bit by bit.

~0115 inverts the octal number 115 bit by bit.
~ 0 1 0 0 1 1 0 1 represents the operand in binary.
————————
1 0 1 1 0 0 1 0

"Left Shift" Operation#

  1. The left operand is the shift operator, and the right operand is an integer expression representing the number of shift bits.
  2. When left shifting, the right end (low bit) is filled with 0; the left end (high bit) that is shifted out is discarded.

char a=6,b;
b=a<<2;
The binary representation of the operation process is as follows:
a:0 0 0 0 0 1 1 0
b=a<<2:0 0 0 1 1 0 0 0

"Right Shift" Operation#

  1. When right shifting, the right end (low bit) that is shifted out is discarded, and the left end (high bit) that is shifted in has two situations: for unsigned integers and positive integers, the high bit is filled with 0; for negative integers, the high bit is filled with 1.

"Bitwise AND" Operation#

  1. Performs a bitwise AND operation on the corresponding bits of the two operands; when both corresponding bits are 1, the result of that bit is 1; otherwise, it is 0.

"Bitwise XOR" Operation#

  1. For the two operands, if the corresponding bits are the same, the result of that bit is 0; if the bits are different, the result of that bit is 1.

"Bitwise OR" Operation#

  1. For the two operands, as long as one of the corresponding bits is 1, the result of that bit is 1; only when both corresponding bits are 0, the result of that bit is 0.

Rules for Operations Between Operands of Different Bit Sizes#

  1. The objects of bit operations can be integer (long int or int or short) and character (char) data.
  2. When the types of the two operands are different, the system will perform the following processing:
    1. First, align the two operands to the right.
    2. Then, expand the shorter operand to the high bit, i.e., fill the left side with 0 for unsigned and positive integers, and fill the left side with 1 for negative numbers, and then perform bitwise operations on the two operands with equal bit sizes.

Chapter Sixteen Files#

16.1 Concept of Files in C Language#

  1. Sequential access
    1. When performing read or write operations, always start from the beginning of the file and read or write sequentially from the beginning to the end.
  2. Direct access (random access)
    1. By calling C language library functions, specify the byte number to start reading or writing, and then directly read or write data at that position.

16.2 File Pointers#

  1. General form: FILE *pointer variable name.

16.3 Opening Files#

  1. General calling form of fopen function: fopen(filename, file usage mode);
    1. If the call is successful, the function returns a pointer of type FILE, assigning it to the file pointer variable fp, thus linking pointer fp with file file_a.
    2. If opening the file fails, it returns NULL.
  2. File usage modes
    1. “r”: Opens a text file for reading; only "read" operations can be performed on the opened file.
    2. “rb”: Opens a binary file for reading; the other functions
Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.