Course Content#
Structs#
- Keyword: struct
- When declaring a struct variable, you need to add struct, and cannot just use the struct name
- struct person Yu;
- When declaring a struct variable, you need to add struct, and cannot just use the struct name
- Assignment and access:
- '.' direct reference——the variable before '.' is a struct variable
- '->' indirect reference——the variable before '->' is a pointer to a struct variable
- Example: a. Go home by myself, b. Tell a friend my home address, come to my house
- Space occupied when declaring struct variables
- Defining a struct does not occupy space
- The sum of the sizes of each variable
- But consider the alignment principle
- ① An integer multiple of the maximum byte size of the members
- ② The offset of the member relative to the starting address of the struct must be divisible by its own size
- If not, fill in bytes after the previous member
- See the example below:
-
-
- Variables a, b, and c cannot be together; the offset of b needs to be a multiple of 4, so the offset of b is 4, and the offset of c is 8
- Reference Detailed Explanation of Struct Alignment——cnblogs
- Space-saving method: define variables of the same type together
- You can use predefined macros to forcibly change the alignment byte size
- Reference Usage of #pragma pack()-Jianshu
- Anonymous struct: struct {...;} var;
- Used only once during initialization
- var is the declared struct variable. Define the struct while declaring the variable
Union#
-
Keyword: union
- Shares a space
- The size of the space is determined by the largest field in the union
-
The significance of unsigned char
-
-
First, we usually understand that a byte does not have a sign bit; more importantly, if the value of a byte is assigned to int, long, etc. (rather than) data types, the system will do some extra work
-
If it is char, the system considers the highest bit as the sign bit, while int may be 16 or 32 bits, so it will extend the highest bit, and the same applies to unsigned int
-
If it is unsigned char, then it will not extend
-
-
Memory usage structure diagram
-
⭐Pointers and Addresses#
-
Learn to operate on the source of the data
-
Address operator: &
- Takes the starting address: the address of the 0th byte
-
Each byte corresponds to an address number
-
64-bit/32-bit: Addressing range
- 32-bit can match up to 4GB of memory
- 2^30 Byte = 1 GB 👉 32-bit supports a maximum of 4 GB
- 32-bit can match up to 4GB of memory
-
Pointer variables
- Used to store addresses, addresses are generally expressed in hexadecimal
- Regardless of the type of pointer (int, char), their status is the same; they all store addresses
- Size occupied: 64-bit - 8 bytes; 32-bit - 4 bytes (64-bit represents the number of bits for the address)
- Can int *p be passed to char *q? Absolutely, both occupy 8 bytes (64-bit)
- The significance of distinguishing types is shown below: equivalent form conversion
- int *p;
- The * is used to indicate that p is a pointer variable during definition
- After definition, p represents the pointer, and the * in *p represents the dereference operation
- Pointer variables are also variables!
- You can use pointer Q to store the address of pointer p
-
Explanation of scanf function
- To modify the value of a variable, you must use address passing
- Parameters that pass addresses can be called output parameters, as the operation will also reflect outside the function
- While the value passing of the function only takes effect within the scope
- To modify the value of a variable, you must use address passing
-
Equivalent form conversion
-
- Dereference operation
- The offset of +1 depends on the byte size of the type represented by p (the significance of distinguishing types)
- Premise: Pointer p points to struct variable a
Function Pointers#
-
Variable: To avoid ambiguity, function variable declarations should be like this
-
- Wrap *add (add is the function name) in parentheses
-
-
Type: typedef can elevate a variable to a type
-
- You can define variables using types
-
-
Two uses of typedef
- Renaming built-in types and struct types
- typedef long long lint;
- typedef char * pcahr; // char * → pchar
- It is somewhat like #define, but there are subtle differences, see code demonstration
- typedef struct __node { int x,y;} Node, *PNode;
- Defines two aliases at the same time
- PNode p; // Can define a pointer variable of Node struct type
- Elevating to a type
- typedef int (*func)(int);
- Can define countless function pointer variables
- typedef int (*func)(int);
- Renaming built-in types and struct types
-
Main function parameters
-
-
Who passes parameters when there are parameters? The operating system
-
return 0; // Returns to the system
-
"echo $?" can be used to determine whether the last command run by the system was successful
- 0: Success
- Non-zero: Not successful
-
Parameter interpretation
- argc: Number of parameters
- argv: Corresponding two-dimensional array, receives argc strings, one-dimensional array receives a line of strings
- *arr[] corresponds to arr[][]
- env: Environment variables
- env is a pointer to char*
- env is an address pointing to the address of a character array
- The env address can also move forward, so it actually corresponds to a two-dimensional character array
- ❓What is the difference between the definitions of **env and *env[]? There is no difference here!
- env is a pointer to char*
- ❓❗Cannot use int ** to represent a two-dimensional array
- Need to use malloc to define?
- Because static arrays seem unable to guarantee continuity
- Here you need to explore online!
- Reference Why can't a secondary pointer directly point to a two-dimensional array-CSDN
-
Question: Zege, I define a two-dimensional array char str[10][10], and cannot use char** to receive it. However, the main function's **env can receive string arrays, how should I understand that string arrays are not considered two-dimensional arrays?
Answer: The latter is dynamically allocated through malloc, which is a dynamic array.
In-class Exercises#
1: Struct Byte Alignment#
-
-
Different definition orders
-
Left: 8 bytes; Right: 12 bytes
2: Union Memory Diagram#
👇
3: Convert IP to Integer#
-
-
192.168.1.2
- Each segment, maximum 255, can be represented with 1 byte, corresponding to unsigned char
- Total is 4 bytes, corresponding to int type
-
Code
-
* In a union, struct must declare a variable * Can sscanf be omitted? If not, it would be inconvenient to read the values of each segment in xxx.xxx.xxx.xxx * Little-endian, big-endian machines * Little → low-order digit → low address * Big → low-order digit → high address
IP (192.168.0.1) stored in little-endian by segment order | ||||
---|---|---|---|---|
int number byte address number | 0 | 1 | 2 | 3 |
IP storage | 1 | 0 | 168 | 192 |
-
-
- Most computers are little-endian
- How to determine if it is little-endian: define int type num = 1, check the value of its highest bit
- Cast the address of int type to char type, then you can read the value at the 0th byte address
- Directly reading the number will read according to the machine's byte order from high/low order, right? Yes
- What to do if the byte order of the local and remote ends does not match
- Process: local byte order → network byte order (unified standard) → remote byte order
- Only when reading must the byte order be distinguished; in other cases, it does not need to be considered
- If it is not detailed to the byte, one should not feel the byte order
- Reference Understanding Byte Order-Ruan Yifeng
- Output
-
-
Additional: Represent a[1].x in as many forms as possible#
[At least 30 forms, using the equivalent forms mentioned earlier, nesting!]
-
-
Code
-
Highlight Notes#
Code Demonstration#
Code#
Demonstration of Struct Offset Calculation, Macro Definition Types and Differences of typedef, Detailed Explanation of Main Function Parameters#
-
-
-
Strings must end with '\0' to facilitate the end of reading judgment (the low bit of num is 0)
-
The address corresponds to long int type (64-bit - 8 bytes, 32-bit - 4 bytes)
-
What are the shortcomings of the commented-out offset() macro definition?
- It still needs to define variables, which will occupy space
- So you can use a null address (0 or NULL) for casting
-
When defining type aliases, macro definitions are just simple replacements, which is not as convenient as typedef
-
Main function input parameters
- Can be divided by spaces, and multiple strings can be integrated using double quotes
-
Program output
-
Additional Knowledge Points#
- In C++ object-oriented programming, structs are a class
- References are more efficient than pointers, as pointers have an extra level of indirection
- How to read a value from a known memory address
- Pass the address to a pointer, then use the dereference operator *
- Syntax sugar
- Refers to a certain syntax added to a programming language that does not affect the functionality of the language but makes it easier for programmers to use
- Makes the program more concise and improves readability
Points for Consideration#
Tips#
-
The focus is on the relationship between pointers and addresses
-
Note-taking is very important
- Typora recording
-
Resume
- You can use ShareLaTeX to create it
- Computer science resumes: black and white, pay attention to indentation, feel solid
-
Refer to textbooks chapters 9 and 10