zoukankan      html  css  js  c++  java
  • 第五章 3 指针(110)

    一 内存与指针

    1、 内存是什么?

    从硬件形态上说,内存就是一条形物理设备,从功能上讲,内存是一个数据仓库,程序内在执行前都要被装载到内存中,才能被中央处理器执行。
    内存是由按顺序编号的一系列存储单元组成的,在内存中,每个存储单元都由唯一的地址,通过地址可以方便地在内存单元中存储信息。
    在计算机中,一切信息都是以二进制数据的形式体现的,每个内存单元的容量是1B,即8bit(8个0、1二进制位)。

    2、内存与CPU读写速度快,断电就没有了,容量比较小,成本比较高,高级服务器,读写很频繁的文件全部存放内存
    3、把一个函数名通过%x打印出main的首地址

    4、一个程序载入内存,代码数据都有地址,外挂就是调用函数,修改数据
    而函数就是代码,变量就是数据
    5、32位的计算机最多的内存容量是4G

    6、变量名就是对内存一段空间里面数据的抽象

    指针变量可以指向任何的一个变量

    int x=10;
    int *p=&x; //p是一个指针变量,p可以是任何变量的地址




    外挂强制修改(用dllinject注射)

    二 指针详解

    1、指针变量在使用之前必须进行初始化。
    int num=100;
    int *p;
    p=# //非法,可以编译,运行报错,会把100当做一个地址

    2、指针只是一个地址,大小是固定的,就是四个字节。
    int *p1;
    double *p2;
    char *p3;
    sizeof(p1); //结果为 4
    sizeof(p2); //结果为4
    sizeof(p3); //结果为4

    3、 指针和地址的区别

    两个要点:一、指针是个量,对应着一块内存区域,二,指针存储的信息是某个内存单元的地址。

    比如: int num=10;
    int *p=#

    //&num 是一个地址,是一个常量
    //而p是一个指针变量,可以存储一个地址

    比如300500是一个地址,
    int *p=(int *)300500 是一个指针,p存储的是地址,指针有类型,从哪里开始,长度是多少,从哪里结束,得知了类型以后,就知道这片内存数据是如何解析

    4、指针变量的声明与初始化

    在声明一个指针后,编译器并不会自动完成其初始化,此时,指针的值是不确定的,也就是说,该指针指向那块内存单元是完全随机的。

    如果在指针变量声明之初确实不知道该将此指针指向何处,最简单的方式是将其置“0”,C语言中提供了关键字NULL

    其基本形式为:
    类型* 指针变量名;

    int *pNum=NULL;

    值为NULL的指针称为空指针,这意味着,指针并不指向任何地址。
    在头文件 stdio.h 中,NULL 定义为常量。

    三 间接访问和直接访问

    1、取地址运算符&, 间接运算符*

    &运算符: 取地址运算符,&m即是变量m在内存中的实际地址。

    *运算符: 指针运算符 (通常称为间接引用运算符),它返回其操作数 (即一个指针)所指向的对象的值.
    如图所示:
    &num 是直接访问变量num的地址,而 (&num)中则是间接访问

    2、 直接访问: 按变量地址存取变量值

    间接访问: 通过存放变量地址的变量去访问变量

    定义指针变量p, &num 直接访问num 的地址,*p通过num的地址间接的访问变量num

    四 打印指针地址

    1、地址格式符:%p %x

    %x: 按照十六进制打印,无意义的0就不打印
    %p: 显示地址的位数,32位,8个十六进制,2^4=16,32位
    显示地址的位数,64位,16个十六进制位,64个二进制位

    int num=10;
    int *p=#
    printf("%x,%x",p,&num);
    printf("\n%p,%p",p,&num);

    打印的格式:

    32为的情况下:

    64位的情况下:

    五 scanf初始化指针


    指针不可以乱指,否则会程序崩溃

    六 指针与函数参数

    c语言要改变外部变量只有传地址,java,c++有引用,c没有

    数组当做参数的时候,传递的是指针

    数组作为参数的时候,改变的是原来的数组

    七 指向指针的指针(二级指针)

    作用

    1、 指针变量也是变量,占据一定的内存空间,有地址,因此可以用一个指针指向它,这称为指向指针的指针,或二级指针。

    2、 函数形式参数,除了数组以外,传递的任何数据,变量,都会新建一个变量接收传入的变量的值。不影响原来的变量,如果是一个数据,传递数据的地址(指针),如果是一个指针,传递指针的地址。

    db是double类型的变量。

    运行结果:

    可以发现main函数的 p的地址和 change函数的 p的地址不相同,
    而是新建一个变量接收传入的变量的值

    3、 *pp=&bd 则改变了指针的指向,**pp=bd

    4、二级指针在外挂应用较多
    编写一个外挂程序,通过二级指针改变一级指针的指向。

    程序的部分代码

    运行生成一个exe程序,打印出各个变量的地址,每3秒打印一次。

    要向上面这个程序中注入dll。通过二级指针改变一级指针的指向来改变
    创建外挂:需要建模块,模块不需要main函数
    新建项目,右键属性将配置类型改为动态库(dll)。 将目标文件名改为
    goA
    需要用到_declspec(dllexport) dll函数导出 接口

    需要改的是指针那么就需要用到二级指针
    打印的结果

    类型不匹配有时会出现偶然的成功现象

    但大多数情况是失败的

    八 指针的类型和指针所指向的类型

    1、 所谓指针类型,指的是声明指针变量时位于变量名前的“类型*”,而所谓指针所指向的类型,指的是为指针初始化或赋值的变量类型。

    2、 不是同一类型的指针,不可以任意赋值。
    不同的数据类型,大小不一样(如果强制赋值的话,就会少读取或多读取,内存有很多垃圾0,1),解析方式不一样

    (1) p1、px 是同一类型的指针,解析px并没有什么错误

    (2) p1、p2 不是同一类型的指针,此时,打印出p2则并不是A.

    3、 同类型指针的赋值
    这是最常见的一种情况,如所示,pN1和pN2是两个相同类型的指针,执行“pN2=pN1;”这样一个赋值操作后,pN1和pN2指向同样的地址,也就是说,两个指针指向同一个内存单元,对pN2的任何改动都会影响pN1的值,反之亦然。

    九 指针的类型和指针所指向的类型不同

    1、 指针除了地址以外还有类型,类型决定了指向的数据大小,决定了数据的解析方式。指针的类型必须要与指针指向的类型一致,一定会出现偏差。即使地址相同,大小相同。

    2、 (1)指向内存字节数大于指针类型占据的字节数

    指针的类型必须要与指针指向的类型一致,不一致,大小不一样,解析方式不一样。
    指针的类型double的大于指针指向的类型int

    	运行结果:
    

    2)指向内存字节数小于指针类型占据的字节数

    指针的类型int的小于指针指向的类型double
    

    	运行结果:
    

    十 指针变量的值

    1、 指针变量的值:
    是指针本身存储的数值,这个值将被编译器当作一个地址,而不是
    一个一般的数值。在32位程序里,所有类型的指针的值都是一个32位整数,因为32位程序里内存地址长度都为32位。
    指针所指向的内存区:
    就是从指针的值所代表的那个内存地址开始,长度为sizeof(指针所指向的类型)的一片内存区。
    指针存储的是地址,地址是首地址,从哪里开始,从哪里结束,由类型决定,
    类型决定长度,决定如何解析。

    2、自己编写外挂改变,通过另外一个程序改变这个进程。
    在上面的代码中添加如下代码,使其打印数据:
    while(1)
    {
    printf("我的级别是%c,我的年龄是%d,我的人民币是%fW",ch,num,db);

    Sleep(5000);
    

    }
    要注入的dll程序
    通过指针直接访问变量的地址,使其通过注入的方式,从而改变它的值,从而改变另一个程序的运行结果

  • 相关阅读:
    SWFObject2.0
    年轻人买房的问题
    百度知道的php爬虫
    PHP解决多进程同时读写一个…
    php快速定位多维数组的深度
    不要用充实的借口去浪费时间
    php跨服务器信息获取之cURL
    为你的生命多积累一些厚度
    看完一定让你很受益!
    phpQuery轻松采集网页内容
  • 原文地址:https://www.cnblogs.com/xingkongcanghai/p/10413872.html
Copyright © 2011-2022 走看看