当前位置:网站首页>指针——黄金阶段
指针——黄金阶段
2022-07-29 01:29:00 【Tandy12356_】
一、指针之间做减法
#include<iostream>
using namespace std;
#include<string>
int main() {
string str[5] = { "周一","周二","周三","周四","周五" };
string* pStr1 = str;
string* pStr2 = &str[5];
int res1 = pStr2 - pStr1;
int res2 = (unsigned int)pStr2 - (unsigned int)pStr1;
return 0;
}
string* pStr1 = str;
009148EB lea eax,[str]
009148F1 mov dword ptr [pStr1],eax
string* pStr2 = &str[5];
009148F7 mov eax,1Ch
009148FC imul ecx,eax,5
009148FF lea edx,str[ecx]
00914906 mov dword ptr [pStr2],edx
int res1 = pStr2 - pStr1;
0091490C mov eax,dword ptr [pStr2]
00914912 sub eax,dword ptr [pStr1]
00914918 cdq
00914919 mov ecx,1Ch
0091491E idiv eax,ecx
00914920 mov dword ptr [res1],eax
int res2 = (unsigned int)pStr2 - (unsigned int)pStr1;
00914926 mov eax,dword ptr [pStr2]
0091492C sub eax,dword ptr [pStr1]
00914932 mov dword ptr [res2],eax
其中 imul ecx,eax,5的作用是将eax*5赋值给ecx
通过mov eax,1Ch不难发现每个string类型的数据长度均为0x1C
即:string类型不管字符串有多长,他的变量本身都是占28个字节
cdq 是一个让很多人感到困惑的指令。 这个指令把 EAX 的第 31 bit 复制到 EDX 的每一个 bit 上。 它大多出现在除法运算之前。它实际的作用只是把EDX的所有位都设成EAX最高位的值。也就是说,当EAX <80000000, EDX 为00000000;当EAX >= 80000000, EDX 则为FFFFFFFF。
例如 :
假设 EAX 是 FFFFFFFB (-5) ,它的第 31 bit (最左边) 是 1,
执行 CDQ 后, CDQ 把第 31 bit 复制至 EDX 所有 bit
EDX 变成 FFFFFFFF
这时候, EDX:EAX 变成 FFFFFFFF FFFFFFFB ,它是一个 64 bit 的大型数字,数值依旧是 -5。
备注:
EDX:EAX,这里表示EDX,EAX连用表示64位数
通过这段汇编指令我们不难发现,指针p2-p1之差是他们的地址之差/数据类型的宽度
而(unsigned int)p2-(unsigned int)p1之差才是指针的地址之差
下面使用int类型的数组再进行测试一遍:
int intArr[5] = { 1,2,3,4,5 };
00218868 mov dword ptr [intArr],1
00218872 mov dword ptr [ebp-0E8h],2
0021887C mov dword ptr [ebp-0E4h],3
00218886 mov dword ptr [ebp-0E0h],4
00218890 mov dword ptr [ebp-0DCh],5
int* pInt1 = intArr;
0021889A lea eax,[intArr]
002188A0 mov dword ptr [pInt1],eax
int* pInt2 = &intArr[5];
002188A6 mov eax,4
002188AB imul ecx,eax,5
002188AE lea edx,intArr[ecx]
002188B5 mov dword ptr [pInt2],edx
res1 = pInt2 - pInt1;
002188BB mov eax,dword ptr [pInt2]
002188C1 sub eax,dword ptr [pInt1]
002188C7 sar eax,2
002188CA mov dword ptr [res1],eax
res2 = (unsigned int)pInt2 - (unsigned int)pInt1;
002188D0 mov eax,dword ptr [pInt2]
002188D6 sub eax,dword ptr [pInt1]
002188DC mov dword ptr [res2],eax
其中sar eax,2右移两位,相当于是乘以4
[荣耀黄金]
NULL从本质上来讲就是0,是C语言里面定义的一个宏
空指针的作用是一旦你访问了空指针,程序就会崩掉,这是好事!
空指针访问报错案例:
#include<iostream>
using namespace std;
#include<string>
int main() {
string girl = "凤姐";
string* lover = &girl;
lover = NULL;
cout << *lover << endl;
return 0;
}
所以最好指针在定义的时候就设置为空!
野指针测试1:
#include<iostream>
using namespace std;
#include<string>
int* getAddr() {
int x = 100;
return &x;
}
int main() {
int* p = getAddr();
cout << *p << endl;
cout << *p << endl;
return 0;
}
打印结果:
根本原因:p指向的地址确实没有发生变化,但是函数一旦调用结束,函数栈里的内存就被回收了,可能刚开始得到的是正确的值,是因为编译器还没有来得及回收
野指针测试2:
int main() {
int* p = (int*)malloc(sizeof(int));
*p = 888;
cout << *p << endl;
printf("p-%p\n", p);
free(p);
cout << *p << endl;
printf("p-%p\n", p);
return 0;
}
野指针指向的位置始终不变,但是那个位置里的数据很有可能已经不在了
避免野指针的办法:指针使用完毕之后置为NULL!
二级指针
判断以下程序是否存在问题:
#include<iostream>
using namespace std;
#include<string>
#pragma warning(disable:4996)
void getMem(char* p, int n) {
p = (char*)malloc(n);
}
int main() {
char* p = NULL;
getMem(p, 100);
strcpy(p, "hello");
cout << p << endl;
free(p);
return 0;
}
运行结果:
修改之后:
#include<iostream>
using namespace std;
#include<string>
#pragma warning(disable:4996)
void getMem(char** p, int n) {
*p = (char*)malloc(n);
}
void add(int x, int y, int z) {
z = x + y;
}
void add2(int x, int y, int* z) {
*z = x + y;
}
int main() {
int x = 100,y=200,z=200;
add(x, y, z);
printf("x-%d y-%d z-%d\n", x, y, z);
add2(x, y, &z);
printf("x-%d y-%d z-%d\n", x, y, z);
char* p = NULL;
getMem(&p, 100);
strcpy(p, "hello");
cout << p << endl;
free(p);
return 0;
}
打印结果:
边栏推荐
- How to write, load and unload plug-ins in QT
- 12.< tag-动态规划和子序列, 子数组>lt.72. 编辑距离
- The growth path of embedded engineers
- Thirty years of MPEG audio coding
- 忽略微信设置字体
- JetPack--Navigation实现页面跳转
- leetcode/和为k的连续子数组个数
- Establish an engineering template based on STM32 in keil -- detailed steps
- What is a proxy server? [2022 guide]
- Solution of Lenovo notebook camera unable to open
猜你喜欢
Implementation of 10m multifunctional signal generator with FPGA
Dynamic memory and smart pointer
[the road of Exile - Chapter 7]
MySQL high performance optimization notes (including 578 pages of notes PDF document), collected
LM13丨形态量化-动量周期分析
数学建模——永冻土层上关于路基热传导问题
Mathematical modeling -- cold proof simulation of low temperature protective clothing with phase change materials
Using local cache + global cache to realize user rights management of small systems
Why can't Bi software do correlation analysis
物联网开发--MQTT消息服务器EMQX
随机推荐
[10:00 public class]: application exploration of Kwai gpu/fpga/asic heterogeneous platform
[cloud native] what is the microservice architecture
弹性布局 单选
IDEA 连接 数据库
QT source code analysis -- QObject (4)
Try to understand the essence of low code platform design from another angle
Solution of Lenovo notebook camera unable to open
Comprehensive analysis of news capture doorway
QT memory management tips
druid. io index_ Realtime real-time query
Web crawler API Quick Start Guide
leetcode/和为k的连续子数组个数
一文读懂Okaleido Tiger近期动态,挖掘背后价值与潜力
什么是作用域和作用域链
Control the pop-up window and no pop-up window of the input box
ciscn 2022 华中赛区 misc
"Wei Lai Cup" 2022 Niuke summer multi school training camp 3, sign in question cajhf
Comprehensive use method of C treeview control
试着换个角度理解低代码平台设计的本质
Add graceful annotations to latex formula; "Data science" interview questions collection of RI Gai; College Students' computer self-study guide; Personal firewall; Cutting edge materials / papers | sh