20160210.CCPP体系详解(0020天)

本文通过一系列程序片段详细介绍了CCPP编程中的指针概念,包括二级指针、反外挂机制、指针类型、指针运算、算数及其他运算的优先级、指针与数组的关系、指针数组、二维数组、动态数组和动态内存管理。通过这些实例,深入探讨了指针在实际编程中的应用和重要性。
摘要由CSDN通过智能技术生成

程序片段(01):01.二级指针.c
内容概要:二级指针

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

//01.二级指针:
//  1.使用场景:
//      (1).跨函数修改一级指针变量的数据-->DLL注入技术!
//      (2).指针数组作为函数形参,将会转化为二级指针-->函数形参!
//  2.使用规律:
//      如何快速定位取值运算符所操作的数据是什么?
//          指针变量(定义级数-取值级数)<==>访问级数!
int main01(void)
{
    int a = 10;
    int b = 15;
    int * p = &a;
    int ** pp = &b;
    *pp = &b;
    **pp = 3;
    //a-->b-->*p-->**pp

    system("pause");
}

程序片段(02):01.反外挂.c
内容概要:游戏反外挂

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

//01.关于赋值运算符的使用特点:
//  赋值运算符针对于普通变量具备自动类型转换特性;
//  赋值运算符针对于指着变量不具备自动类型转换的特性
//02.指针类型与指针变量类型的重要性!
//  只要涉及到指针的操作,一定要时刻注意类型的重要性
//  注:数据类型<=>解析(步长+方式)
//03.数组名以及指向数组首元素的指针区别:
//  1.数组名和指向数组首元素的指针的数值层面一样
//  2.数组名和指向数组首元素的指针都存在内存实体
//      数组名:内存实体不可修改
//          常量指针变量的指向不可改变,但是指向的数据可以改变
//      指向数组首元素的指针(分变量指针和常量指针的情况)
//          视指针变量的const修饰关键字使用情况而定
//04.通过一级指针变量来模拟反外挂原理:
//  一级指针变量当中的指针指向数组当中的某个血量刻度;
//  通过修改一级指针变量的指针指向来获取具体的血量刻度;
//  从而实现血量不可修改,只能修改指向(实现血量的只读权限)
int main01(void)
{
    double  arr[100];
    for (int i = 0; i < 100; ++i)
    {
        arr[i] = i + 1;//1.0~100.0
    }
    double * p = arr + 60;//类型很重要,类型决定了(解析步长+解析方式)-->直接的一个数组名只是具备该数组首元素的内存首地址(首个字节)
    printf("&p = %p \n", &p);
    printf("&arr = %p \n", arr);
    printf("%f \n", *p);
    while (1)
    {
        printf("此时的血=%lf \n", *p);
        Sleep(1000);
    }

    system("pause");
}

程序片段(03):01.挂.c
内容概要:

_declspec(dllexport) go01()
{
    double * p1 = 0x2ef4a4;
    double * p2 = 0x2ef4bc;
    //p1 = p2 + 92;//整数倍
}

//01.动态库函数的导出接口:
//  _declspec(dllexport)
//02.二级指针变量的用途:
//  注入技术修改二级指针变量的数据
//03.区分数值意义层面的整数
//  没有数据类型的特点
//04.指针变量的指针如果只是加上
//  一个普通的数值,那么最好是该指针所                                                                                                     
//  指向内存块儿的内存字节整数倍!
//  避免数据解析失败!
//05.无论是自动类型转换还是强制类型转换
//  都只是在对内存当中的二进制数据副本进行操作;
//  原本数据不会被修改!
_declspec(dllexport) go()                  
{
    double ** pp = 0x0018FAE4;//这里的pp+1<=>pp+1*(所存储的一级指针变量所占用的内存尺寸)
    //double * p = 0xB9F5D4;//p+1任何指针类型的变量都可以存储一个地址,地址本身无类型的情况之下,只能当做一个普通数据
    //*pp = 0xB9F5D4 + 0x50;//p+3普通的整数没有类型可言,只是一个数值层面的意义
    //*pp = *pp + 2;//修改方式1(明确类型)
    //*pp = 0x0018F794 + 3 * sizeof(double);//修改方式2(不明类型)-->错误,因为sizeof();会返回有类型的整型数值
    *pp = 0x0018FAFC + 3 * 8;//修改方式2(正确方式)
    //int a = 10;
}

程序片段(04):01.指针类型.c
内容概要:指针类型

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

//01.指针的类型以及指针变量的类型重要性:
//  1.数据类型:决定了(解析方式+解析步长)
//  2.关于数据类型所决定的解析方式一共有三大类:
//      (有符号整型+无符号整型+浮点型),这三种类型
//      即使解析步长一样,如果解析方式不一样,解析结果照样异常!
//  3.指针的类型决定了通过取值运算符进行取值运算的时候
//      需要通过指针的数据(等同于内存首地址),向前解析的内存字节数
//  4.printf();函数不会进行数据类型的转换,只是根据格式控制符所描述
//      的解析方式对内存当中的二进制数据进行对应的解析
//  注1:赋值号对于指针变量没有类型转换的意义,只有数值层面的意义!-->数值意义(地址数值,没有类型概念)
//      赋值号只对于普通变量才存在着类型转换的意义!-->类型意义
//  注2:指针变量的类型决定了取值运算符对指针变量当中所存储的指针的解析细节!
int main01(void)
{
    int num = 10;
    int * p1 = &num;
    void * p3 = &num;//空类型的指针变量只是用于存储具备地址意义的数值,不含解析细节!
    double * p2 = &num;
    printf("%p, %p \n", p1, p2);//指针变量所存储的地址数值都一样
    printf("%lf, %d \n", *p2, *p1);//但是指针变量的类型决定了取值运算福对指针变量当中的指针解析方式

    system("pause");
}

//02.任何类型的变量进行赋值的时候,
//  都应当注意数据类型是否一致!
int main02(void)
{
    int a = 10;
    int * p1 = &a;
    int * p2 = p1;//类型一致的指针变量指针可以进行指针的赋值操作
    printf("%p, %p \n", p1, p2);//格式控制符只是描述对于内存二进制数据的解析方式
    printf("%d, %d, %d \n", *p1, *p2, a);
    //*p1 = 4;
    a = 2;
    printf("%d, %d, %d \n", *p1, *p2, a);

    system("pause");
}

//03.只要指针变量的类型和指针类型不一致
//  就绝对不能正确的解析到结果
int main03(void)
{
    int num = 10;
    double db = 10.9;
    int * p1 = &num;
    double * p2 = p1;//获取p2这个指针所指向的数据的时候,由于该指针变量(p2)的所描述的解析(方式+步长)不正确,因此解析出来的结果不可预料
    //赋值号,指针除了指针变量以外的其他变量,都会存在自动类型转换机制,唯独指针类型的变量特殊(只有地址意义的数值)
    //int a = 10.9;
    void *px = p1;
    px = p2;//空类型的指针变量只是用于临时存储地址意义的变量
    printf("%d \n", (int)db);//printf();不会进行自动类型转换,会导致解析某些数据失败
    printf("%lf \n", (float)num);

    //double * p = &num;
    //printf("%lf \n", *p);
    //*p = &db;
    //p = &db;
    //printf("%lf \n", *p);
    int *p = &db;
    printf("%d \n", *p);

    system("pause");
}

//04.sizeof关键字用于求取实际占用的内存字节数!
//  返回内存字节数类型为unsigned int
//05.严格注意:
//  是具体给指针变量赋值还是给普通变量赋值
//  注:通过指针变量+取值运算符访问到的可能是普通内存实体!
//      赋值运算符针对于普通内存实体也是具备自动类型转换机制的!
//06.关于自动类型转换机制:
//      两种处理方式
//          同为整型:直接截断(图形化操作二进制位)
//          不同类型:根据解析方式+解析步长进行决断!
int main04(void)
{
    int num = 100;
    int * p = &num;//sizeof(int)--int **pp-->sizeof(int *)
    *p = 10.9;
    printf("%d \n", num);
    printf("%u \n", sizeof(int *));
    printf("%d \n", sizeof(double *));

    system("pause");
}

//07.三个不同类型的指针变量所存储的地址是一样的
//  但是由于指针变量的类型不一致,也就导致了指针类型不一致
//  因此,对于同一个地址所对应的内存实体的解析方式也就不一样!
//08.对局部变量的查询方式:
//  局部变量的值+根据局部变量的值进行解析后的结果
int main05(void)
{
    int num = -1;
    int * p1 = &num;
    unsigned int * p2 = &num;
    float * p3 = &num;

    system("pause");
}

程序片段(05):01.Test.cpp+02.指针.c
内容概要:指针的运算

///01.Test.cpp
#include <stdio.h><
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尹成

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值