c语言指针简单描述,C语言指针的简单理解

从最开始学习编程就对C充满了好奇。之前由于工作的原因没有去深入的了解,对于指针一直处于一知半解的状态。这次研究安卓逆向开发,就顺道一起研究了。

基本步骤:

1、将好久没有更新过的VS先更新一下

2、安装C语言开发需要的组件

3、去网上简单回顾下C语言的语法

新建一个C++的空项目,VS没有新建C的项目。因为C++是完全兼容C的所有直接新建C++项目是没有问题的。

424640535e2c?utm_campaign=hugo

image.png

在源文件添加一个新建项hello.c,随便打印一个hello。

#include

int main() {

printf_s("%s", "hello");

return 0;

}

printf_s() 是printf的安全版本,在VS2017中已经不允许使用printf(),其他版本能不能用目前没有验证过。

#include

int main() {

int a,* a_ptr; // 随便定义一个变量a和一个a_ptr指针

a = 9527;//给a赋值

a_ptr = &a; // &变量 表示取变量的地址

printf_s("变量a地址:%p\n",a_ptr); // 将指针的值打印出来,这个值就是代表了变量a的内存地址

printf_s("a_ptr指针对应地址的值:%d", *a_ptr); // 将a_ptr 进行解引用输出指针对应地址的值

return 0;

}

其实直接看上面的代码也不难理解了,&表示取地址,*表示取值

上面的代码定义了一个变量和一个指针,先给变量赋值为9527。接着将a变量的地址给a_ptr指针

我们直接把一个变量赋值给指针的值会发生什么呢?

#include

int main() {

int a,* a_ptr; // 随便定义一个变量a和一个a_ptr指针

a = 9527;//给a赋值

*a_ptr = a; // 直接将a赋值给指针的值

return 0;

}

424640535e2c?utm_campaign=hugo

image.png

上面的代码直接报错了,因为指针没有初始化

我们继续尝试,如果将一个变量的值赋值给一个指针会发生什么,我们看看下面的代码

int main() {

int a,* a_ptr; // 随便定义一个变量a和一个a_ptr指针

a = 9527;//给a赋值

a_ptr = a; // 直接将a赋值给指针的值

printf_s("%p", a_ptr);

return 0;

}

424640535e2c?utm_campaign=hugo

image.png

打印地址可以看到输出的2537,9527的16进制就是等于2537,可以看到是完全没有问题的。

我们再来看看数组

#include

int main() {

float a[5] = { 0,1.0,2.0,3.0,4.0 };

printf_s("数组的起始地址:%p\n数组的第三个元素:%f\n数组占用多少字节%d", a, *(a + 2), sizeof(a));

return 0;

}

424640535e2c?utm_campaign=hugo

image.png

可以看到数组a输出的是一个指针地址,在C语言可以通过

a[0] // a[下标]的方式进行取值

也可以向上面代码一样通过指针偏移进行取值,a+1偏移的地址是数组类型对应的字节数,int类型偏移4个字节,cha类型偏移1个字节,数组元素都是连续存储的,地址依次从低到高。上面数组的值应该是

a = 00F7FECC; // 数组a的地址

[*(a),*(a+1),*(a+2),*(a+3),*(a+4)];

接下来我们再看看二维数组

#include

int main() {

int a[2][3] = { {0,1,2}, {4,5,6} };

printf_s("数组的起始地址:%p\n数组的第二个元素:%p\n数组占用多少字节%d\n", a, *(a + 1), sizeof(a));

return 0;

}

424640535e2c?utm_campaign=hugo

image.png

上面我们可以看到这是一个二维数组,int占4个字节,总共6个元素,所用总共占用了24个字节。当我们打印第二个元素的时候发现也是一串地址,应该可以得出a是一个二级指针。这时候我们需要怎么取值呢。

*(*a) // 先使用一个*取二维数组的地址,然后再用一个*取二维数组的第一个元素的值

根据上面的语法我们来试一下,代码如下:

#include

int main() {

int a[2][3] = { {0,1,2}, {4,5,6} };

// printf_s("数组的起始地址:%p\n数组的第二个元素:%p\n数组占用多少字节%d\n", a, *(a + 1), sizeof(a));

printf_s("取第一个数组的第二个元素值:%d",*(*a + 1));

return 0;

}

前面我们一直都是再获取值,下面看看怎么改值:

#include

int main() {

int a[2][3] = { {0,1,2}, {4,5,6} };

// printf_s("数组的起始地址:%p\n数组的第二个元素:%p\n数组占用多少字节%d\n", a, *(a + 1), sizeof(a));

*(*a + 1) = 7; // 将第一个数组的第二个元素值修改成7

printf_s("取第一个数组的第二个元素值:%d",*(*a + 1));

return 0;

}

424640535e2c?utm_campaign=hugo

image.png

基本到这里就差不多了,其实本篇文章的目的是为了看懂下面一段Android源码:

424640535e2c?utm_campaign=hugo

image.png

readUnsignedLeb128(const u1** pStream)

函数是有个二级指针pStream的参数

首先先解释一下u1类型,u1表示一个字节无符号数

const u1* ptr = *pStream;

将pStream 进行解引用,赋值给一级指针ptr

int result = *(ptr++);

将指针ptr偏移一个字节并解引用。赋值给result

if(result>0x7f){

...

}

这个目的是判断字节最高位是否为1,到这里关于指针的部分就so easy了,剩下的就是一些位的操作,就不讲了

424640535e2c?utm_campaign=hugo

image.png

将自己学习的过程记录下来也是一种学习,文章里有不对的地方欢迎指出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值