基本数据类型的表现形式(地址,指针,引用)
1 必要知识
地址:只有变量才有地址,常量没有地址,除了const定义的伪常量。
指针(TYPE *):任何数据类型都可以定义指针,指针本身也是一种数据类型。由于指针保存的都是地址(32位操作系统下,地址为32位),所以无论什么类型的指针都占据4字节空间。
引用(TYPE&):在C++中不能单独定义,定义就要初始化,是一个变量的别名。
2.指针的工作方式
2.1 指针寻址
因为指针只保存首地址,使用类型修饰符修饰指针(TYPE *),能够解释这个地址中的数据类型,数据类型不同,占用的空间就不同。
举例分析:
1 #include <iostream> 2 3 #pragma warning(disable:4996) 4 5 using namespace std; 6 7 int main() 8 { 9 int Value = 0x12345678; 10 int* iptr = &Value; 11 char* cptr = (char*)& Value; 12 short* sptr = (short*)& Value; 13 14 printf("%08x\n", *iptr); 15 printf("%08x\n", *cptr); 16 printf("%08x\n", *sptr); 17 18 system("PAUSE"); 19 return 0; 20 }
数据在内存中的存储为"78 56 34 12","78"为首地址,
指针iptr为int型指针,以int类型(4字节大小)对地址进行解释,以小端方式取出数据,"12345678"。指针cptr类似原理,取出1字节数据,"78"。指针sptr取出两字节数据,"5678"。
同理,可以推理指针加法的工作方式。
举例说明
1 #include <iostream> 2 3 #pragma warning(disable:4996) 4 5 using namespace std; 6 7 int main() 8 { 9 int Value = 0x12345678; 10 int* iptr = &Value; 11 char* cptr = (char*)& Value; 12 short* sptr = (short*)& Value; 13 14 printf("%08x\n", *iptr); 15 printf("%08x\n", *cptr); 16 printf("%08x\n", *sptr); 17 printf("\n"); 18 iptr += 1; 19 cptr += 1; 20 sptr += 1; 21 printf("%08x\n", *iptr); 22 printf("%08x\n", *cptr); 23 printf("%08x\n", *sptr); 24 25 system("PAUSE"); 26 return 0; 27 }
iptr += 1; 00735096 add eax,4 00735099 mov dword ptr [ebp-18h],eax cptr += 1; 0073509C mov eax,dword ptr [ebp-24h] 0073509F add eax,1 007350A2 mov dword ptr [ebp-24h],eax sptr += 1; 007350A5 mov eax,dword ptr [ebp-30h] 007350A8 add eax,2 007350AB mov dword ptr [ebp-30h],eax
通过汇编代码可以看出,指针加法也是根据指针类型进行解释。
iptr+=1,向后推移4字节后,再以int型解释地址,输出数据。
cptr+=,向后推移1字节后(首地址变成"56"),再以char型解释地址,取1字节数据,输出"56"。
sptr类似... ...
3.引用
引用实际上是C++为了简化指针操作,对指针进行了封装,让使用者看不到存放地址的内存空间。
举例说明
int main() { int num = 0x12345678; int* iptr = # int& iref = num; return 0; }
汇编代码
int main() { 00C016F0 push ebp 00C016F1 mov ebp,esp 00C016F3 sub esp,0E8h 00C016F9 push ebx 00C016FA push esi 00C016FB push edi 00C016FC lea edi,[ebp+FFFFFF18h] 00C01702 mov ecx,3Ah 00C01707 mov eax,0CCCCCCCCh 00C0170C rep stos dword ptr es:[edi] 00C0170E mov eax,dword ptr ds:[00C0A004h] 00C01713 xor eax,ebp 00C01715 mov dword ptr [ebp-4],eax 00C01718 mov ecx,0C0C000h 00C0171D call 00C011FE int num = 0x12345678; 00C01722 mov dword ptr [ebp-0Ch],12345678h int* iptr = # 00C01729 lea eax,[ebp-0Ch] 00C0172C mov dword ptr [ebp-18h],eax int& iref = num; 00C0172F lea eax,[ebp-0Ch] 00C01732 mov dword ptr [ebp-24h],eax return 0; 00C01735 xor eax,eax }
4.常量
常量数据在程序运行之前就已经存在了。可以使用#define或者const来定义常量。
#define是一个真常量,而const是由编译器判断实现的常量,是一个假常量。在编译器进行检查时,发现const定义的变量一个常量值,会将程序中所有该变量替换为常量值。
举例说明
#include <iostream> using namespace std; int main() { const int num = 0x12345678; int* ptr = (int*)& num; *ptr = 0x2; int count = num; printf("%08x\n", num); printf("%08x\n", *ptr); system("PAUSE"); return 0; }
由于编译器提前替换了num,所以我们在改变常量值后输出num依然是更改前的值,而ptr指向的是现在内存中的常量值。
原文地址:https://www.cnblogs.com/Mayfly-nymph/p/11564803.html
- 小程序中图片高度等比缩放
- 三分钟使用 Python 处理 Nginx 日志
- Python,Shell 和 三个标准文件
- 【微信官方】获取用户信息方案介绍
- 【实战】如何使用 Python 从 Redis 中删除 4000万 KEY
- [多图] DevOps 也要懂点 Excel
- [实战篇] Python 运维中使用并发
- PHP数据结构(十) ——有向无环图与拓扑算法
- PHP数据结构(十一) ——图的连通性问题与最小生成树算法(1)
- 优化 MySQL: 3 个简单的小调整
- PHP数据结构(十一) ——图的连通性问题与最小生成树算法(2)
- 进程间通信的历史与未来
- PHP数据结构(十二) ——静态查找表
- 小程序中滚动条的使用,wx.pageScrollTo和<scroll-view>的对比
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- windows下搭建spark测试环境
- 微信小程序实时语音识别实践
- 轻量安全的部署方案
- 阿里2020.7.31笔试
- 聊聊dubbo-go的PrometheusReporter
- 聊聊dubbo-go的apolloConfiguration
- 看了这篇,关于浏览器缓存你还有哪些疑问?
- 深入分析Volatile的实现原理
- Java Collection Framework : List
- String类的equals方法
- 必须同时重写hashcode和equals方法的原因
- Springboot中使用Redis的发布/订阅模式
- Java 几种排序算法 与时间空间复杂度
- JAVA程序员必须要学会的网络知识
- 计算机网络学习--数据链路层