博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android NDK开发之旅2 C语言基础 指针
阅读量:6996 次
发布时间:2019-06-27

本文共 2701 字,大约阅读时间需要 9 分钟。

###指针

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

###指针的意义

没有指针就没有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. 在函数传参的时候,通过指针的方式,函数对值的修改会影响到调用的地方。

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

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

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

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

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

####注意:

  1. 添加动态库DLL的输出声明:__declspec(dllexport)。
  2. 把项目的输出改为DLL,而不是EXE。(VS里面:解决方案--属性--常规)。
  3. 通过DllInject.exe软件把DLL注入到游戏中,就可以发现游戏时间修改为99999了。

###空指针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

###函数指针(与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语音的回调机制里面非常重要。

如果觉得我的文字对你有所帮助的话,欢迎关注我的公众号:

我的群欢迎大家进来探讨各种技术与非技术的话题,有兴趣的朋友们加我私人微信huannan88,我拉你进群交(♂)流(♀)

转载地址:http://swdvl.baihongyu.com/

你可能感兴趣的文章
8-5 泛型类型擦除
查看>>
正文处理命令及tar命令
查看>>
实习第三周小记-----生活在于经历 分类: 程序人生 ...
查看>>
将excel中的数据转为json格式
查看>>
字典操作
查看>>
[洛谷P2839][国家集训队]middle
查看>>
《求一个数组的连续的最大子数组之和》
查看>>
设置行间距,自适应文字大小
查看>>
资金流学习-广州发展
查看>>
python基础3(元祖、字典、深浅copy、集合、文件处理)
查看>>
正确编写Designated Initializer的几个原则
查看>>
iOS播放动态GIF图片
查看>>
获取版本号
查看>>
使用jdk自带的visualVM监控远程监控was
查看>>
集合视图UICollectionView 介绍及其示例程序
查看>>
JsLint 的安装和使用
查看>>
合并傻子//区间dp
查看>>
让IE和Chrome都以隐身模式启动
查看>>
MyPython-->进阶篇-->类
查看>>
unity remote 连接设置
查看>>