指向指针的指针

Posted saintdingspage

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了指向指针的指针相关的知识,希望对你有一定的参考价值。

  • 占有内存空间就有地址,有地址就可以被指针指向,如果指针作为一个参数,那么改变它就需要指针的地址,指针的指针在这种场景下就应孕而生

注意,命令double *pp = &p;

在c++中编译错误,在c中也会产生警告信息

void main()
{
    int earning = 12000;
    double *p = &earning;
    //double *pp = &p;//p的地址为4个字节,pp指向的数据类型double占用8个字节
    //pp++执行后前进8个字节 p++前进4个字节,不匹配所以,此行代码非法
    printf("p的大小是%d,double类型大小%d
", sizeof(p), sizeof(double));
    double**pp = &p;//这样引入了一个崭新的数据类型(double*)double指针类型
    printf("p的大小是%d,double*  指针类型大小%d
", sizeof(p), sizeof(double*));
    system("pause");
}

技术图片

 

 一级指针装载变量的地址

二级指针装载指针地址,由此我们可以改变指针的指向,游戏外挂中使用很多。

  • 模拟游戏外挂原理
第一步:

准备一段代码模拟苏联图-128截击机的载油情况,这段代码试图捕捉到代码执行过程中各关键变量的地址,然后交给指针的指针修改 #include<stdio.h> #include<stdlib.h> void main() { int fuelindex = 100; int fuelindex_m = 66; int fuelindex_l = 23; printf("fuelindex:%x ",&fuelindex); printf("fuelindex_m:%x ", &fuelindex_m); printf("fuelindex_l:%x ", &fuelindex_l); char fuellevelhigh = h, fuellevelmedium=m, fuellevellow=l; printf("高级载油量地址为:%x ", &fuellevelhigh); printf("中级载油量地址为:%x ", &fuellevelmedium); printf("低级载油量地址为:%x ", &fuellevellow); char *fuellevel = &fuellevelhigh; system("pause"); }

输出结果:

技术图片

 

 第二步:编写模块

如果你使用了微软的vs2013集成开发环境,选中解决方案----添加----新建项----visual C++-----常规-----空项目,命名完成后,选中源文件----添加----新建项,开启一个.c文件,我命名为gametrick.c,

然后选中gametrick.c----属性----配置属性----目标文件扩展名选择.dll

往这个文件写入一个函数,在函数体之前添加 _declspec(dllexport);(尽管到目前为止,我也弄不清这是什么,但是就先加上吧)

_declspec(dllexport) void go()
{
    //int *p = 0xcffbcf;//这样还不够,因为仅仅知道表示地址的值0xcffbcf,但并不知道是什么类型
    //也就无从知道执行前进操作时,前进几步
    //所以
    int *p = (int *)0x12ff964;
    *p = 87;
}

写完后在IDE 找到生成--生成,这样就生成了一个动态链接库文件

技术图片

 

 

接下来运行你的主程序,打开DLL注入文件,选中主程序文件对应的那个进程

#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>


void main()
{
    int fuelindex = 100;
    int fuelindex_m = 66;
    int fuelindex_l = 23;
    printf("fuelindex:%x
",&fuelindex);
    printf("fuelindex_m:%x
", &fuelindex_m);
    printf("fuelindex_l:%x
", &fuelindex_l);

    char fuellevelhigh = h, fuellevelmedium=m, fuellevellow=l;
    printf("高级载油量地址为:%x
", &fuellevelhigh);
    printf("中级载油量地址为:%x
", &fuellevelmedium);
    printf("低级载油量地址为:%x
", &fuellevellow);
    char *fuellevel = &fuellevelhigh;
    while (1)
    {
        printf("
载油量是%d,%c", fuelindex, fuellevelhigh);
        Sleep(3000);//为避免打印过于频繁,需要暂缓执行,引入windows.h函数
    }
    system("pause");
}

注入,生成的模块

技术图片

 

 

技术图片

 

 看到图中第一行显示的载油量地址为 12ff964,添加到模块文件时,需要改为0x12ff964

 

 通过指针的指针改变值,不知你是否也这样倒霉,弄了一下午,就是改不对

_declspec(dllexport) void cpc()
{
    //char*p = 0xcffbcf;//这样还不够,因为仅仅知道表示地址的值0xcffbcf,但并不知道是什么类型
    //也就无从知道执行前进操作时,前进几步
    //所以
    char **p = (char **)0xeffd47;
    *p = (char*)0xeffd3b;
}

这种改法,感觉很不稳定

技术图片

 

 总之指针的指针赋值的时候:

类型适配规范:

下列代码侥幸会成功

#include<stdlib.h>

void main()
{
    char mark = Z;
    char *tomark = &mark;
    char **tochar = tomark;
    printf("%x", tomark);
    system("pause");
}

而下列代码即使运行时不报错,也一定会导致异常结果

void main()
{
    double mark = 3.1415826;
    double *tomark = &mark;
    double *tochar = &tomark;
    printf("mark大小:%d,tomark大小:%d,tochar大小:%d
", sizeof(double *), sizeof(&mark), sizeof(tomark));
    printf("tochar的结果:%lf
",*tochar);
    getchar();
}

输出结果:

 

 技术图片

 

 究其原因是一个一级指针A变量,如果存入了另一个一级指针B的地址,那么就意味着给指针A分配了大小为4的空间,但是double类型的长度是8,这就导致了溢出,从而造成实际结果不准确

有影像资料显示,2014年时,vs2013平台上该上机实验会导致报错,现在是2019年可能c语言的标准发生了一些改变,或者微软做了某些优化处理,但类型不匹配导致的数值不准确的风险的确存在!!!

void main()
{
    double mark = 3.1415826;
    double *tomark = &mark;
    double *tochar = (double *)tomark;//所以这一步的类型强转必不可少
    printf("tochar的结果:%lf
", *tochar);
    getchar();
}

 输出结果:

技术图片

 

 这种四舍五入是正常的,因为double只能容纳8位

以上是关于指向指针的指针的主要内容,如果未能解决你的问题,请参考以下文章

Objective-C Block与函数指针比较

内存、指针和指向指针的指针

梦开始的地方 —— C语言: 函数指针+函数指针数组+指向函数指针数组的指针

C++ 指向指针的指针

函数指针

指向 const 指针(或指向 const 的指针)