前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C语言第八讲,指针*

C语言第八讲,指针*

作者头像
IBinary
发布2018-03-30 12:06:51
6610
发布2018-03-30 12:06:51
举报
文章被收录于专栏:逆向技术逆向技术

            C语言第八讲,指针*

一丶简单理解指针

说到指针,很多人都说是C语言的重点. 也说是C语言的难点.

其实指针并不是难.而是很多人搞不清地址 和 值.以及指针类型.

为什么这样说.

假设有两个变量,如下

代码语言:javascript
复制
int nNum1 = 1;
int nNum2 = 0x00401000;

变量nNum1 保存的值是1

变量nNum2 保存的是一个16进制数值.

那么如果我们把保存16进制的这个变量.当作指针. 也就是说它保存了一个16进制数值而已. 我们可以通过16进制找到里面存储的值.

但是因为是保存地址的变量.所以我们需要加上特殊符号进行定义.

例如:

代码语言:javascript
复制
int *nNum2 = 0x004010000;

指针其实就是保存了一个特殊的数值而已. 而通常这个数值我们说是地址.

如果我们保存了1的地址,那么我们就可以访问1了.

怎么访问?

可以通过取内容符号进行访问.

代码语言:javascript
复制
int nNum = 1;
int *p = &nNum1; //保存1的地址,我们可以不用管.也可以理解为一个16进制数值而已.
*p = 3;  //修改地址空间的值.

二丶指针的数据类型

说到指针.其实我们说的并不是保存地址的难点.难点是该如何解释这个地址.

例如我们知道定义一个变量.我们可以知道这个变量的内存空间跟随这数据类型走.

例如:

代码语言:javascript
复制
int nNum1 = 3;  //nNum1 大小是4个字节.  则 sizeof(nNum1) = 4;
short int nNum2 = 2; // nNum2 大小是2个字节. 则sizeof(nNum2) = 2;
....

那么我们指针其实也一样.也和普通变量一样.

代码语言:javascript
复制
int nNum1 = 2;
int *p = &nNum1;  p的大小也是4个字节. 跟地址无关.

比如我们定义指针的是否有很多数据类型解释.

例如:

代码语言:javascript
复制
int *p;

short *p;

double *p;

那么地址解释的方式也就不一样.

根据上图可以得知,1所占的内存空间是4个字节,而不同的类型则有不同的解释方式.

如果解释为short *,则获得的是1的高位,如果解释为int *则是整个的1所代表的值.

三丶指针的运算

指针和我们普通变量运算不一样.

普通变量进行运算

代码语言:javascript
复制
int nNum1 = 1;
nNum1 ++;  //nNum1 = 2;

指针变量进行运算

代码语言:javascript
复制
int *p = 0x00401000;
p++;  则P的值是0x00401004;
因为我们的类型是 int *解释方式,所以每次+1则是加一个int类型大小.而因为指针就是地址.
所以+1的时候就是+4

指针相减也是一样的.

四丶指针和数组的的组合

学习了指针,就要说下指针应用的场合. 数组和指针一般是很常见的.

例如定义数组:

代码语言:javascript
复制
int nNum1[10] = {1,2,3,4,5,6,7,8,9,10};

指针可以进行访问数组.

代码语言:javascript
复制
int *p = nNum1; //注意,数组是一个数据结构.所以我们不用加取地址符号.数组名就是数组的首地址.
如果我们是变量,则需要加上&符号.
例如:   
   int n = 10;
    int *p = &n;
指针进行访问:
    *p = 10; //数组元素的第一项更改为10
    p++;      //指针++,根据数据类型来相加,+1等于+4,则到数组的第二个元素了.

一般遍历数组的时候我们会封装成一个函数.

则会写成下面这样.

代码语言:javascript
复制
void IteratorArr(int *p, int Count)
{
    while (Count--)      //遍历的个数自减
    {
        printf("%d \t",*p);
        p++;              //数组元素自加
    }
    puts("\r\n");
}
int main()
{
    int Arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    IteratorArr(Arr,sizeof(Arr)/sizeof(Arr[0]));//传入数组首地址即可.但是我们函数的参数要定义为指针. 还需要传入数组的个数.进行遍历.
    system("pause");
    return 0;
}

输出结果.

五丶指针和函数的应用.

指针一般也用于函数的传参.例如上面我们遍历数组.其中我们的函数的形参就是指针.

如果在函数中想更改实际参数的值. 也可以用到指针.例如我们上一篇讲解函数的时候留下的一个小话题.

代码语言:javascript
复制
void ChangeValue(int *p, int *p1)
{
    *p = 0;        //传过来的是nNum1的地址,所以我们直接*地址对其更改即可.
    *p1 = 11;
}
int main()
{
    int nNum1 = 10;
    int nNum2 = 11;
    ChangeValue(&nNum1,&nNum2);
    printf("nNum1 = %d  nNum2 = %d\r\n",nNum1,nNum2);
    system("pause");
    return 0;
}

输出结果.

函数指针.

指针的高级应用还有函数指针. 就是我们定义一个指针. 这个指针是函数指针.可以指向自己定义的一个函数.

函数名字就是函数的首地址.

例如:

代码语言:javascript
复制
void ChangeValue(int *p, int *p1)
{
    *p = 0;
    *p1 = 11;
}
int main()
{
    int nNum1 = 10;
    int nNum2 = 11;
    ChangeValue(&nNum1,&nNum2);
    
    int(*p)(char const* const _Format, ...);         //定义函数指针
    p = printf;                                     //函数指针p指向了printf
    p("nNum1 = %d  nNum2 = %d\r\n",nNum1,nNum2);    //调用p实际和调用printf一样
    system("pause");
    return 0;
}

输出结果.

 函数指针的语法

代码语言:javascript
复制
函数返回值 (*  指针变量名)(函数参数)

函数指针其实很好定义,只需要把函数的声明拿过来,然后函数名字前边加上括号. 括号里面加上*就可以了.

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-02-28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  •             C语言第八讲,指针*
    • 一丶简单理解指针
      • 二丶指针的数据类型
        • 三丶指针的运算
          • 四丶指针和数组的的组合
            • 五丶指针和函数的应用.
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档