首页 > 编程语言 >C++指针等于地址加偏移量

C++指针等于地址加偏移量

时间:2024-10-02 19:00:15浏览次数:7  
标签:short 偏移量 int long char 地址 C++ 指针

概述

本文通过c++示例代码演示指针的加减法运算及对 “指针 = 地址 + 偏移量” 的理解。

研究示例

1. 首先来检查各种变量类型所占的内存大小

#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. 各类型的指针进行加减运算

各类型的指针进行加减运算是以元素为单位进行加减,而非地址的最小单位(1个Byte)。以下演示各类型指针指向的地址:

#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;    // char指针在使用cout输出会直接打印变量而非地址,要加(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;
}

输出:(char, short, int, long long的指针的最小移动单位分别是1, 2, 4, 8 Byte,刚好是对应的单个元素的类型所占内存大小)

*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

说明:指针 = 地址 + 偏移量。即指针除了包含地址信息之外,还包含解析这个地址的方式(从该地址开始向后读取多少个Byte),因此“指针就是地址”的说法是不准确的,一个int* p1和char* p2 指向的地址可能是相同的,但是解析这个地址的方式是不同的。

3. 强制转换指针类型对地址进行解析

可以强行指定指针的类型对同一块内存的数据进行不同方式的解析。例如:

#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;
}

输出:

*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

解释如下图:arr数组在内存中占10个Byte,分别定义了三种类型的指针char*, short*, int*并且都指向首地址arr[0],则三种指针的差异体现在两个方面:1、解引用(解析地址)时的偏移量分别为1,2,4个Byte;2、加减时分别以1,2,4个Byte为单位移动地址。

注意:

1、本编译器采用小端模式,因此*p_short = 0x0100 而非 0x0001。

2、*(p_int + 2)访问到了未知的内存,因此结果中打印出来了不受控制的数据"0xfdf60908",警示了我们在使用指针时,尤其是涉及到类型转换、加减运算、赋值等操作时,一定要避免指针越界,否则将会产生不可预知的危险后果。

总结

本文通过几个简单的c++程序验证了 “指针 = 地址 + 偏移量” 这一结论,希望能对指针如何操作内存有更深入的理解。

另外,本文所讨论的指针均为变量指针,而函数指针不能进行加减运算(会报warning: pointer to a function used in arithmetic),我会另写一篇文章讨论函数指针。

标签:short,偏移量,int,long,char,地址,C++,指针
From: https://www.cnblogs.com/phyjack/p/18444984

相关文章

  • 南沙C++信奥赛陈老师解一本通题 1966:【14NOIP普及组】比例简化
    ​ 【题目描述】在社交媒体上,经常会看到针对某一个观点同意与否的民意调查以及结果。例如,对某一观点表示支持的有1498人,反对的有902人,那么赞同与反对的比例可以简单的记为1498:902。不过,如果把调查结果就以这种方式呈现出来,大多数人肯定不会满意。因为这个比例的数值太大......
  • 南沙C++信奥赛陈老师解一本通题 1820:【00NOIP提高组】进制转换
    ​ 【题目描述】我们可以用这样的方式来表示一个十进制数:将每个阿拉伯数字乘以一个以该数字所处位置的(值减1)为指数,以10为底数的幂之和的形式。例如,123可表示为1*10^2+2*10^1+3*10^0这样的形式。与之相似的,对二进制数来说,也可表示成每个二进制数码乘以一个以该数字所处位置......
  • c++ vector容器、字符串
    c++vector容器          字符串:           ......
  • 理解C语言之深入理解指针(四)
    目录1.回调函数是什么?2.qsort使⽤举例2.1使⽤qsort函数排序整型数据2.2使⽤qsort排序结构数据3.qsort函数的模拟实现1.回调函数是什么?        回调函数就是⼀个通过函数指针调⽤的函数。        如果你把函数的指针(地址)作为参数传递给另⼀个......
  • 南沙C++信奥赛陈老师解一本通题 1984:【19CSPJ普及组】纪念品
    ​ 【题目描述】小伟突然获得一种超能力,他知道未来 T 天 NN种纪念品每天的价格。某个纪念品的价格是指购买一个该纪念品所需的金币数量,以及卖出一个该纪念品换回的金币数量。每天,小伟可以进行以下两种交易无限次:1.任选一个纪念品,若手上有足够金币,以当日价格购买该纪念品;2......
  • C++中指针和数组相关的运算符优先级
    概述本文深入介绍了与指针和数组相关的运算符优先级,利用代码示例展示了当左结合和右结合运算符同时存在时的结合方式,同时也演示了如何使用()来强制人为指定结合顺序。指针、数组相关的运算符优先级下表展示了相关运算符的优先级,有4个级别,同级别内的运算符按照结合性依次调用。......
  • CSCI1120 Introduction to Computing Using C++
    CSCI1120IntroductiontoComputingUsingC++,Fall2024/25DepartmentofComputerScienceandEngineering,TheChineseUniversityofHongKongCopyright©2024CSE,CUHKPage1of8Assignment2:GumballMachinesDue:23:59,Thu3Oct2024Filename:gumball.......
  • C++类型参数化
     C++程序设计语言继承于C程序设计语言并且增加面向对象的程序设计思想。面向过程的编程和面向对象的开发设计编程思想的区别在于数据的处理类型。C语言的程序设计基于基础的数据类型。结构体struct的概念设计是基础数据类型数据的组合。C++程序设计的开发增加类class的数据构建......
  • GESP C++四级样题卷
    (满分:100分考试时间:90分钟)PDF试卷及答案回复:GESPC20234一、单选题(每题2分,共30分)1.在C++中,指针变量的大小(单位:字节)是()A2B4C8D与编译器有关2.以下哪个选项能正确定义一个二维数组()Ainta[][];Bcharb[][4];Cdoublec[3][];Dboold[3][......
  • C++和OpenGL实现3D游戏编程【连载12】——游戏中音效的使用
    1、游戏中音效的使用前面我们实现了图片纹理的显示功能,是不是感觉到非常的简单。那么今天我们就继续说下游戏声音的实现。音效也是游戏的灵魂,只有搭配了美妙动听的音效以后,游戏才能令人耳目一新,与玩家产生良好的效果。音效文件最常用的可分为两种,分别为.wav和.mp3后缀的......