Play C pointer
Some time ago I listened to the csdn online lecture class on Embedded C learning pointer. Below are my study notes, and I noted down some important knowledge points, which are not comprehensive, even learning tips.
1. Check the following code:
# Define int_t int * <br/> typedef int * int_t; <br/> void main () {<br/> int_t P1, P2; <br/> int_t Q1, q2; <br/>}
The two definitions are different.
The first case is that before compilation, the compiler replaces INT_T in the Code with int *, so INT_T p1, p2; equivalent to int * p1, p2; so p1 is the pointer to the int type, and p2 is the int type variable.
In the second case, typedef defines int * as a type called int_t, so q1 and q2 all point to int type pointers.
Deep Dive:
In the C or C ++ language source program, an identifier is allowed to represent a string, which is called a "macro ". The identifier defined as "macro" is called "macro name ". During compilation and preprocessing, all the "macro names" in the program are replaced by the strings in the macro definition. This is called "macro replacement" or "macro expansion ". Macro definition is completed by macro definition commands in the source program. Macro replacement is automatically completed by the Preprocessing Program.
Typedef declaration, or typedef for short, creates a new name for an existing type. For example, typedef is often used to write more beautiful and readable code. The so-called beauty means that typedef can hide clumsy Syntax structures and platform-related data types to enhance portability and future maintainability. This article will do its best to reveal the powerful features of typedef and how to avoid some common traps.
2. Programming suggestions:
Add the _ t suffix to the names of all custom types (for example, types defined by typedef) to facilitate program reading.
3. Check the following code:
Int main () {<br/> int ** p; <br/> int a; <br/> * p = & a; <br/> return 0; <br/>}
This code can be compiled, but it may cause a segment error. The reason is that ** p points to the unknown memory space, resulting in a segment error. ** P is a second-level pointer, which stores the address of * p, and * p points to int variable. But here * p is not declared or defined, so it is an unknown, inaccessible memory space, and ** p points to it, resulting in a segment error.
The pointer must point to an accessible and known memory space.
The above code is changed to the following:
Int main () {<br/> int ** p; <br/> int * q; <br/> int a; <br/> q = &; <br/> p = & q; <br/> return 0; <br/>}
In actual programming, you must pay attention to this problem to ensure that the Pointer Points to accessible, known memory space, otherwise it will cause imperceptible errors.
3. Function interfaces must be stable. 4. directly changing the parameter value of the function in C language is invalid for the caller. If you need to change the value of the form parameter, the pointer will be used, or a reference in C ++.
Deep Dive:
In C language, the function call mechanism determines that directly changing the parameter value is invalid for the caller. Because calling a function opens up a new space, the variables declared in the call function are valid only in this function. When the function call ends, the compiler Automatically releases the space. The form parameter of this function is only the real parameter passed by the caller.Copy,Changing the copy value does not affect the value of the parameter in the caller.In C, parameters are equivalent to local variables.If the pointer is used, the parameter in the call function is a copy of the address of the object to change the value. Changes to the content of the copy pointing to the space will affect the value of the object in the caller. References in C ++ point to the alias of a variable. Note the difference between them and pointers.
5. Check the following code:
Int * func (void) {<br/> int B = 200; <br/> return & B; <br/>}
This code snippet is incorrect. According to the function calling mechanism mentioned above, variable B is a local variable, and its memory space is released by the compiler after the function is called, therefore, the returned address points to an unknown and inaccessible memory space, resulting in a segment error.
Deep Dive:
The function can return the global variable pointer, static variable pointer, and memory block pointer allocated by malloc. It cannot return the pointer of a local variable.
6. Check the following code:
Void main () {<br/> int * p; <br/> char * q; <br/> p ++; // move four bytes backward <br/> q ++; // move one byte backward <br/>}
The pointer variable increases progressively, and the number of bytes is the size of the space occupied by the object to which it points.
Struct Test * sp; <br/> sp ++; // shift sizeof (struct Test) byte to the back
7. Check the following code:
Int main () {<br/> int a = 0x12345678; <br/> printf ("% x/n", * (char *) & )); // display result: 78 <br/> printf ("% x/n", * (short *) & a); // The display result is: 5678 <br/> printf ("% x/n", * (int *) & a); // The displayed result is: 12345678 <br/>}
Ah, the drawing software openoffice.org in ubuntu cannot be saved as jpg files, so I have to say it myself. In the memory space, a occupies 4 bytes, char is 1 byte, and short is 2 bytes. In the first output, & a is forcibly converted to a pointer to the char type, so only the content in the first byte after & a points to the address is displayed, that is, 78. similarly, the second output is 5678. The third is naturally 12345678. This example shows that the pointer must specify its meaning to the variable type.
8. Check whether the system is a function of the big-end method or small-end method by default.
Int test_endian (void) {<br/> int a = 0x12345678; <br/> return * (char *) & a) = 0x78; <br/>}
The return value uses a logical expression, which is very concise.
I hope the above notes will help you.