summarize
This article demonstrates the addition and subtraction of pointers through c++ sample code and the use of the"Pointer = Address + Offset" of understanding.
Research Examples
1. First check the size of the memory occupied by the various variable types
#include <iostream>
using namespace std;
int main(){
cout << sizeof(char) << endl; // 1 Byte
cout << sizeof(short) << endl; // 2 Byte
cout << sizeof(int) << endl; // 4 Byte
cout << sizeof(long long) << endl; // 8 Byte
return 0;
}
2. Adding and subtracting pointers of various types
Pointers of each type perform addition and subtraction operations by adding or subtracting elements, not the smallest unit of an address (1 Byte). The following demonstrates the addresses pointed to by each type of pointer:
#include <iostream>
using namespace std;
int main(){
char *p_char = new char('a');
cout << "*p_char = " << *p_char << endl;
cout << "p_char = " << (void*)p_char << endl; // charThe pointer is used in thecoutThe output will print the variable directly instead of the address,require an additional(void*)
cout << "p_char + 1 = " << (void*)(p_char + 1) << endl;
cout << "p_char + 2 = " << (void*)(p_char + 2) << endl;
cout << "p_char - 1 = " << (void*)(p_char - 1) << endl;
short *p_short = new short(456);
cout << "*p_short = " << *p_short << endl;
cout << "p_short = " << p_short << endl;
cout << "p_short + 1 = " << p_short + 1 << endl;
cout << "p_short + 2 = " << p_short + 2 << endl;
cout << "p_short - 1 = " << p_short - 1 << endl;
int *p_int = new int(123);
cout << "*p_int = " << *p_int << endl;
cout << "p_int = " << p_int << endl;
cout << "p_int + 1 = " << p_int + 1 << endl;
cout << "p_int + 2 = " << p_int + 2 << endl;
cout << "p_int - 1 = " << p_int - 1 << endl;
long long *p_long_long = new long long(456789);
cout << "*p_long_long = " << *p_long_long << endl;
cout << "p_long_long = " << p_long_long << endl;
cout << "p_long_long + 1 = " << p_long_long + 1 << endl;
cout << "p_long_long + 2 = " << p_long_long + 2 << endl;
cout << "p_long_long - 1 = " << p_long_long - 1 << endl;
return 0;
}
Output: (the smallest unit of movement for pointers to char, short, int, long long is 1, 2, 4, 8 Byte, respectively, which just happens to be the size of memory occupied by the type of the corresponding individual element)
*p_char = a
p_char = 0xe41600
p_char + 1 = 0xe41601
p_char + 2 = 0xe41602
p_char - 1 = 0xe415ff
*p_short = 456
p_short = 0xe41620
p_short + 1 = 0xe41622
p_short + 2 = 0xe41624
p_short - 1 = 0xe4161e
*p_int = 123
p_int = 0xe41640
p_int + 1 = 0xe41644
p_int + 2 = 0xe41648
p_int - 1 = 0xe4163c
*p_long_long = 456789
p_long_long = 0xe41660
p_long_long + 1 = 0xe41668
p_long_long + 2 = 0xe41670
p_long_long - 1 = 0xe41658
Description:Pointer = Address + OffsetThat is, the pointer contains not only the address information but also the way to resolve the address (how many bytes are read back from the address). That is, in addition to the pointer contains the address information, but also contains the way to parse the address (from the address to read how many Bytes backward), so the "pointer is the address" is not accurate, an int * p1 and char * p2 pointed to the address may be the same, but the way to parse the address is different.
3. Force conversion of pointer types to resolve addresses
It is possible to force the type of a pointer to be parsed in different ways for data in the same block of memory. Example:
#include <iostream>
using namespace std;
int main(){
char arr[10] = {0,1,2,3,4,5,6,7,8,9};
unsigned int l = sizeof(arr)/sizeof(arr[0]);
char* p_char = arr;
cout << "*p_char = " << (int)*p_char << endl;
cout << "*(p_char + 1) = " << (int) *(p_char + 1) << endl;
cout << "*(p_char + 2) = " << (int)*(p_char + 2) << endl;
cout << "*(p_char + 3) = " << (int)*(p_char + 3) << endl;
cout << "*(p_char + 9) = " << (int)*(p_char + 9) << endl;
short* p_short = (short*)arr;
cout << hex << "*p_short = " << *p_short << endl;
cout << hex << "*(p_short + 1) = " << *(p_short + 1) << endl;
cout << hex << "*(p_short + 2) = " << *(p_short + 2) << endl;
int *p_int = (int*)arr;
cout << hex << "*p_int = " << *p_int << endl;
cout << hex << "*(p_int + 1) = " << *(p_int + 1) << endl;
cout << hex << "*(p_int + 2) = " << *(p_int + 2) << endl;
return 0;
}
Output:
*p_char = 0
*(p_char + 1) = 1
*(p_char + 2) = 2
*(p_char + 3) = 3
*(p_char + 9) = 9
*p_short = 100
*(p_short + 1) = 302
*(p_short + 2) = 504
*p_int = 3020100
*(p_int + 1) = 7060504
*(p_int + 2) = fdf60908
Explanation of the following figure: arr array in memory occupies 10 Byte, respectively, defined three types of pointers char *, short *, int * and are pointing to the first address arr [0], then the difference between the three types of pointers is reflected in two aspects: 1, dereferencing (resolve the address) when the offset were 1,2,4 Byte; 2, plus or minus were 1,2,4 Byte to move the address.
Attention:
1. This compiler uses small end mode, so *p_short = 0x0100 instead of 0x0001.
2, * (p_int + 2) access to the unknown memory, so the results printed out in the uncontrolled data "0xfdf60908", warning us in the use of pointers, especially when it comes to type conversion, addition and subtraction operations, assignments, etc., we must avoid pointers to cross the border, otherwise there will be unpredictable and dangerous consequences.
summarize
This paper verifies with a few simple c++ programs that the"Pointer = Address + Offset" This conclusion will hopefully lead to a deeper understanding of how pointers manipulate memory.
In addition, the pointers discussed in this article are variable pointers, and function pointers can not be added or subtracted (will report warning: pointer to a function used in arithmetic), I will write another article to discuss function pointers.