Course Content#
Structures#
- Keyword: struct
- When declaring a structure variable, you need to add struct, and cannot just use the structure name
- struct person Yu;
- When declaring a structure variable, you need to add struct, and cannot just use the structure name
- Assignment and access:
- '.' direct reference——the variable before '.' is a structure variable
- '->' indirect reference——the variable before '->' is a pointer to a structure variable
- Example: a. Go home by myself, b. Tell a friend my home address, come to my house
- Space occupied when declaring structure variables
- Defining a structure does not occupy space
- The sum of the occupied space of each variable
- But consider the alignment principle
- ① An integer multiple of the maximum number of bytes occupied by the members
- ② The offset of the member relative to the starting address of the structure can be divided by its own size
- If not, fill in bytes after the previous member
- See the example below:
-
-
- Variables a, b, 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 Structure Alignment——cnblogs
- Space-saving method: define variables of the same type together
- You can use predefined macros to forcibly change the alignment byte count
- Reference Usage of #pragma pack()-Jianshu
- Anonymous structure: struct {...;} var;
- Used only once during initialization
- var is the declared structure variable. Define the structure while declaring the variable
Union#
-
Keyword: union
- Shares a space
- The size of the space is determined by the maximum memory occupied field in the union
-
The significance of unsigned char
-
-
First, we usually understand that a byte has no 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, then 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 goes for assigning to unsigned int
-
If it is unsigned char, then it will not extend
-
-
Memory occupancy structure diagram
-
⭐Pointers and Addresses#
-
Learn to operate on the essence of data
-
Address operator: &
- Takes the starting address: the address of the 0th byte
-
Each byte corresponds to an address label
-
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 variable
- Used to store addresses, addresses are generally represented in hexadecimal
- Regardless of the pointer type (int, char), their status is the same; they all store addresses
- Space 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 seen 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 *p's * represents the value retrieval 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
- However, 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
-
- Value retrieval operation
- The offset of +1 depends on the byte count of the type represented by p (the significance of distinguishing types)
- Premise: Pointer p points to structure variable a
Function Pointers#
-
Variable: To avoid ambiguity, function variable declarations should be like this
-
- Put *add (add is the function name) in parentheses
-
-
Type: typedef can elevate variables to types
-
- You can use type definitions for variables
-
-
Two usages of typedef
- Renaming built-in types and structure types
- typedef long long lint;
- typedef char * pcahr; // char * → pchar
- A bit 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 structure type
- Elevating to a type
- typedef int (*func)(int);
- Can define countless function pointer variables
- typedef int (*func)(int);
- Renaming built-in types and structure types
-
Main function parameters
-
-
Who passes the 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-0: 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 define with malloc?
- 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: Structure Byte Alignment#
-
-
Different definition orders
-
Left: 8 bytes; Right: 12 bytes
2: Union Memory Diagram#
👇
3: IP to Integer#
-
-
192.168.1.2
- Each segment, maximum 255, can be represented with 1 byte, corresponding to unsigned char
- A total of 4 bytes, corresponding to int type
-
Code
-
* In union, struct must declare variables * Can we avoid sscanf? If not, it would be inconvenient to read each segment's value in xxx.xxx.xxx.xxx * Little-endian, big-endian machines * Little → low digit of number → low address * Big → low digit of number → high address
IP (192.168.0.1) stored in little-endian machine 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 get the value at the 0th byte address
- Reading the number will read according to the machine's byte order from high/low bit, 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 you distinguish byte order; in other cases, you don't need to consider it
- If not detailed to bytes, you 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 Structure Offset Calculation, Macro Definition Types and Differences with typedef, Detailed Explanation of Main Function Parameters#
-
-
-
Strings must end with '\0' for easy termination 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 are not as convenient as typedef
-
Main function input parameters
- Can be divided by spaces; multiple strings can be integrated using double quotes
-
Program output
-
Additional Knowledge Points#
- In C++ object-oriented programming, a structure is a class
- References are more efficient than pointers, as pointers have an extra level of passing
- How to read a value based on a known memory address
- Pass the address to a pointer, then use the value retrieval operator *
- Syntax sugar
- Refers to a certain syntax added to a computer language that does not affect the functionality of the language but makes it easier for programmers to use
- Makes programs 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 for recording
-
Resume
- You can use ShareLaTeX for this
- Computer-oriented resumes: black and white, pay attention to indentation, feel solid
-
Refer to chapters 9 and 10 of the reference book