打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Android NDK 开发之旅 2--C 语言基础--指针

1

 指针

指针是一个变量,也叫指针变量,存放的是变量的地址(内存地址,系统给数据分配的编号(门牌号)),有类型之分。

指针的意义

没有指针就没有Java的面向对象(OOP)。

指针的定义与基本使用示例

void change(int* p){ *p = 300;}void main(){ int i = 90; int* p = &i; //输出指针指向的地址 printf("%#x\n" , p);//p的值就是i这个变量的内存地址 //通过指针间接给i赋值 *p = 200; printf("%d\n" , i); change(p); printf("%d\n" , i); system("pause");
}

注意

  1. 指针通过 类型* 指针名字来定义,可以赋值为变量的地址。

  2. 可以通过指针间接给变量赋值。

  3. 在函数传参的时候,通过指针的方式,函数对值的修改会影响到调用的地方。

2

 趣味例子--游戏外挂原理

先写一个游戏,运行,初始化一个游戏时间。

#include <stdlib.h>
#include <stdio.h>
#include <Windows.h>
void
main(){ //游戏时间 int time = 600; //打印出time的地址 printf("%#x\n",&time); while(time>0){ time--; printf("游戏时间剩余%d秒\n",time); Sleep(1000);//#include <Windows.h> } system("pause");
}

再创建一个工程,作为外挂,去修改游戏的时间:

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

__declspec(dllexport) void go(){ //修改游戏时间 int* p =(int*)0x55feb4;//注意:这个地址是游戏打印出来的 *p = 99999;
}

注意:

  1. 添加动态库 DLL 的输出声明:__declspec(dllexport)。

  2. 把项目的输出改为 DLL,而不是 EXE。(VS 里面:解决方案--属性--常规)。

  3. 通过 DllInject.exe 软件把 DLL 注入到游戏中,就可以发现游戏时间修改为 99999 了。

3

指针类别

空指针NULL

void main(){ int i = 0; int* p = NULL; printf("%#x\n" , p);//输出NULL的地址,就是0x0 //某些比较小的地址操作系统不允许访问(访问冲突) //*p =100; system("pause");
}

多级指针(主要讨论二级)

指针变量保存的是变量的地址,可以是一个指针变量的地址,这时候就是多级指针了。

多级指针的意义:

  1. 动态内存分配二维数组,操作数组的时候。

  2. 在 jni.h 中的 struct JNIEnv 结构体等有用到。

例子:

void main(){ int a = 50; int* p1 = &a; int** p2 = &p1;//p2是一个二级指针,存放的是p1的值(即a的地址) printf("%d",**p2); system("pause");
}

指针运算(加减法)(与数组的操作相结合)

void main(){ //数组在内存中是连续存储的 //指针的运算在数组遍历的时候才有意义 //ids+i等价于&ids[i] //二维数组的行指针、列指针 //*(ids+i)等价于ids[i] int ids[] = {0,1,2,3,4,5}; //数组的首地址,下面都是一个意思 int* p = ids; printf("%#x\n",ids); printf("%#x\n",&ids[0]); printf("%#x\n",&ids); printf("%d\n",*p); p++;//指针的加减法,移动sizeof(数据类型)个字节 printf("%d\n",*p);//输出的是数组中的数据1 //通过指针给数组赋值 //高级写法([]运算符的重载) int i =0; for (;i<5;i++) { ids[i] =10; } //普通写法(利用指针) p=ids; for (;p<ids+5;p++) { *p=10; } system("pause");
}

函数指针(与 Java 中的回调类似)

函数指针的定义与基本使用

void msg(char* msg , char* title){ //C语言里面字符串用char指针代替 MessageBox(0,msg,title,0);}void main(){ //直接调用 //msg("内容","标题"); //函数指针的定义:返回类型,指针名字,参数列表(后面也可以通过typedef关键字来定义一个新的类型) //参数名可以省略 //定义一个函数指针,指向msg函数 void(*fun)(char* msg, char* title) = msg; //使用函数指针去间接调用msg函数 fun("我爱你","李璐"); system("pause");
}

函数指针的例子

int add(int a , int b){ return a+b;}int minus(int a , int b){ return a-b;}void msg(int(*function_p)(int a , int b) ,int a,int b){ //调用函数指针的函数 int res = function_p(a,b); printf("%d\n",res);}void main(){ msg(add , 1,2); msg(minus ,2,1); system("pause");
}

注意

  1. 可以看到,msg 函数调用的时候需要传一个函数指针,参数是两个整型,返回值是整型。msg 函数的执行需要执行我们手动传入的代码(函数),从而实现了回调(注入代码)。

  2. 函数指针的使用,Java 中 new 内部类,类似 Java 的回调(比回调更加强大)。

  3. 函数指针,提高复用性,在 C 语音的回调机制里面非常重要。

4

本系列

Android NDK 开发之旅 1--C 语言基础--基本数据类型

读者须知

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
C语言中sizeof与strlen区别
C语言面试题
C语言难点分析整理
考查嵌入式C开发人员的最好的0x10道题
计算机二级学习网址
C语言学习教程第六章-指针(6)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服