I am Lao Wen, an embedded engineer who loves learning.Follow me to become even better together!Pointers are everywhere Many beginners in C language find pointers quite difficult. In fact, pointers are present in many aspects of our lives, and we use them all the time. They make our lives more convenient. Without pointers, life would be inconvenient, don’t believe it? Look at the example below. Here is a real-life example: Suppose you ask me to lend you a book, and I arrive at your dorm, but you are not there, so I place the book on your shelf in room 2, number 3, and write a note to put on your desk. The note says: The book you wanted is on the shelf in room 2, number 3. When you return and see this note, you will know where I placed the book I lent you. Think about it, the function of this note: the note itself is not the book, nor does it contain the book. So how do you know the location of the book? Because the note indicates the location of the book! In fact, this note is a pointer. The content on it is not the book itself, but the address of the book, and you found the book I lent you through this pointer note. All data in a computer must be stored in memory, and different types of data occupy different numbers of bytes; for example, an int occupies 4 bytes, while a char occupies 1 byte. To access this data correctly, each byte must be numbered, just like house numbers or ID numbers, where each byte’s number is unique, allowing you to accurately find a specific byte. The following image shows the numbering of each byte in 4GB of memory (in hexadecimal): We refer to the numbering of bytes in memory as addresses (Address) or pointers (Pointer). Addresses start from 0 and increase sequentially; in a 32-bit environment, the memory available to the program is 4GB, with the smallest address being 0 and the largest address being 0XFFFFFFFF. The following code demonstrates how to output an address:
#include <studio.h>
int main(){ int a = 100; char str[20] = "EmbedIoT Studio"; printf("%#X, %#X \n", &a, str); return 0;}
The output is:
0X28FF3C, 0X28FF10
%#X indicates output in hexadecimal format with the prefix 0X. a is a variable used to store an integer, and you need to add & to get its address; str itself represents the address of the string, so no & is needed.Everything is an address C language uses variables to store data and functions to define reusable code segments, and they all must be placed in memory for the CPU to use. Data and code are stored in memory in binary form, and the computer cannot distinguish whether a block of memory stores data or code based on format. When a program is loaded into memory, the operating system assigns different permissions to different memory blocks; memory blocks with read and execute permissions are code, while those with read and write permissions (or possibly only read permissions) are data. The CPU can only access code and data in memory through addresses, and during program execution, it will inform the CPU of the addresses of the code to execute and the data to read/write. If a program accidentally makes a mistake, or if a developer intentionally does so, and provides the CPU with an address in the code area when it is supposed to write data, a memory access error will occur. This memory access error will be intercepted by hardware and the operating system, forcing the program to crash, leaving the programmer no chance to recover. The CPU needs addresses to access memory, not variable names and function names! Variable names and function names are merely mnemonics for addresses; when the source file is compiled and linked into an executable program, they are all replaced with addresses. An important task during the compilation and linking process is to find the addresses corresponding to these names. Suppose the addresses of variables a, b, and c in memory are 0X1000, 0X2000, and 0X3000 respectively, then the addition operation c = a + b; will be converted into something like the following:
0X3000 = (0X1000) + (0X2000);
( ) indicates a value retrieval operation; the entire expression means to retrieve the values at addresses 0X1000 and 0X2000, add them together, and assign the result to the memory at address 0X3000. Variable names and function names provide us with convenience, allowing us to use easily readable and understandable English strings while writing code, without having to face binary addresses directly, which would be quite overwhelming. It is important to note that although variable names, function names, string names, and array names are essentially the same, they are all mnemonics for addresses, but during coding, we consider variable names to represent the data itself, while function names, string names, and array names represent the starting addresses of code blocks or data blocks.Source: Internet.
-END-
Previous Recommendations: Click the image to jump to read
The basic process and considerations for embedded product development
Started an open-source IoT project, let’s dive into embedded systems together!
What pitfalls are there in the field of embedded technology?