前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >指针(二)

指针(二)

作者头像
DeROy
发布2020-05-11 11:39:53
3260
发布2020-05-11 11:39:53
举报
文章被收录于专栏:编程学习基地编程学习基地

一、指针和数组

区别:

指针可以申请一块内存当作数组使用 数组直接定义使用

相同点

  • 都可以管理一块内存
  • 指针和数组都可以用 * 和 [ ] 访问内存
代码语言:javascript
复制
1#include<stdio.h>
2int main()
3{
4    int arr[4] = { 0,1,2,3 };
5    int *temp = arr;
6    //arr[1]和*(arr+1)等效
7    printf("arr[1]:%d\n*(temp+1):%d", *(arr + 1),temp[1]);
8    return 0;
9}

不同点

  • sizeof(数组名)得到数组大小,sizeof(指针)得到指针大小
  • 指针可以++,--,数组名不可以
  • 指针可以重新指向 可以重新申请一块更大的内存(动态数组大小可变),静态数组定义之后大小就固定了

注意

  • 数组名作为函数实参传参的时候退化成指针
  • sizeof(任何类型的指针)的值都是4(32位系统下)

在解释指针数组和数组指针之前先来解释下数组的存储结构

代码语言:javascript
复制
1//定义一个二维数组
2int a[3][4] = { { 1,3,5,7 },{9,11,13,15},{17,19,21,23} };

那么它的存储结构如下图:

a[0]是a[ 0 ] [ 0 ]的地址,也是a数组的首地址

同理,a[1]是a[ 1 ] [ 0 ]的地址,a[2]是a[ 2 ] [ 0 ]的地址

指针数组

指针数组:存放指针的数组 本质是数组,数组元素是指针

代码语言:javascript
复制
1int*  arr[3];        //指针数组  10个int*
  • 指针数组和数组的搭配使用
代码语言:javascript
复制
 1#include<stdio.h>
 2int main()
 3{
 4    int arr[3][4] = { { 1,3,5,7 },{9,11,13,15},{17,19,21,23} };
 5    int *p[3];
 6    for(int i=0;i<3;i++)
 7    {
 8        p[i] = arr[i];  //指针数组指向二维数组每行的首地址
 9    }
10    //输出指针数组指向的数组
11    for (int i = 0; i < 3; i++)
12    {
13        for (int j = 0; j < 4; j++)
14            printf("%d\t", p[i][j]);
15        putchar(10);    //换行
16    }
17    return 0;
18}
数组指针

也称行指针表示方法:int(*p)[n] 数组指针:指向一个整型的一维数组,这个一维数组的长度是n

  • 数组指针一般和数组搭配使用
代码语言:javascript
复制
 1#include<stdio.h>
 2int main()
 3{
 4    int arr[3][4] = { { 1,3,5,7 },{ 9,11,13,15 },{ 17,19,21,23 } };
 5    int(*p)[4] = arr;   //指针数组指向数组arr
 6    //打印指针数组指向的值
 7    for (int i = 0; i < 3; i++)
 8    {
 9        for (int j = 0; j < 4; j++)
10            printf("%d\t", *(*(p + i) + j)); //printf("%d\t",p[i][j]);
11        putchar(10);
12    }
13    getchar();
14    return 0;
15}
代码语言:javascript
复制
1在这里我想解释下为什么 *(*(p + i) + j)) 和 p[i][j] 等价;
2指针数组的表示方法:int(*p)[n]
3p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n;
4n也可以说是p的步长,也就是说执行p+1时,p要跨过n个整型数据的长度。
5
6*(p+i) == p[i] == &p[i][0] == arr[i] == &arr[i][0]         (==是等价的意思)
7*(*(p + i) + j) == *(p[i] + j) == p[i][j]
8
9在数组的存储结构里就是第i行的第j个元素

二、二级指针

指向指针的指针,称为 二级指针

任何数据都有地址,一级指针的值虽然是地址,但是这个地址做为一个数据也需要空间来存放,而二级指针就是就是来存储这个地址的。

二级指针定义和使用
  • 二级指针的简单用法
代码语言:javascript
复制
1#include<stdio.h>
2int main()
3{
4    int a = 10;
5    int *p = &a;
6    int **pp = &p;
7    printf("&a:%p\np:%p\n*pp:%p\n**pp:%d\n", &a, p, *pp, **pp);     //%p打印地址
8    return 0;
9}

打印结果:

代码语言:javascript
复制
1&a:000000B0CB1EF964
2p:000000B0CB1EF964
3*pp:000000B0CB1EF964
4**pp:10
代码语言:javascript
复制
1二级指针的一次解引用 *pp    得到所指向一级指针的地址,也就是p的值
2
3二级指针的两次解引用 **pp  得到所指向一级指针指向的值 也就是a的值
二级指针和指针数组

二级指针可以直接访问二维数组吗?答案当然是不行的,那么如何访问二维数组呢?

通过指针数组间接访问数组

代码语言:javascript
复制
 1#include<stdio.h>
 2int main()
 3{
 4    int arr[3][4] = { { 1,3,5,7 },{9,11,13,15},{17,19,21,23} };
 5    int *p[3];
 6    for (int i = 0; i < 3; i++)
 7    {
 8        p[i] = arr[i];  //指针数组指向二维数组
 9    }
10    int **pp = p;       //二级指针指向指针p
11    for (int i = 0; i < 3; i++)
12    {
13        for (int j = 0; j < 4; j++)
14            printf("%d\t", pp[i][j]);
15        putchar(10);    //换行
16    }
17    return 0;
18}

三、指针函数和函数指针

指针函数

返回值为指针的函数,本质是一个函数,而该函数的返回值是一个指针

例如 malloc() 函数,或者自定义的函数如:

代码语言:javascript
复制
1int* add(int x,int y);

所谓的指针函数也没什么特别的,和普通函数相比就是指针函数返回一个指针

函数指针

指向函数的指针

  • 定义格式:类型 (*指针名) (参数)
代码语言:javascript
复制
1int (*p)(int x, int y);
  • 函数指针的调用
代码语言:javascript
复制
 1#include<stdio.h>
 2int add(int x, int y)
 3{
 4    return x + y;
 5}
 6int main()
 7{
 8    int (*p)(int x, int y); //定义函数指针
 9    p = add;    //函数指针p指向函数add
10    printf("第一种方法:%d\n第二种方法:%d", (*p)(1, 2), p(2, 3));//函数指针的两种调用方法
11    return 0;
12}

四、和指针有关的传参

根据传参类型分类

  • 普通变量 int a;
代码语言:javascript
复制
1//函数原型
2void fun(int x);
3//函数调用
4fun(a);
  • 地址 int a;
代码语言:javascript
复制
1//函数原型
2void fun(int* p);
3//函数调用
4fun(&a);
  • 数组

一维数组:int arr[3];

代码语言:javascript
复制
1//函数原型
2void fun(int* p);
3void fun(int arr[]);    //推荐这种,让人一看就知道你要传的是数组
4//函数调用
5fun(arr);

二维数组:int arr[3] [3];

代码语言:javascript
复制
1//函数原型
2void fun(int(*p)[3]);
3void fun(int[][3]);        //行省略,列不能省略 
4//函数调用
5fun(arr);

指针数组:int*p[3];

代码语言:javascript
复制
1//函数原型
2void fun(int* p[3]);
3void fun(int** p);
4//函数调用
5fun(p);

函数名:add();

代码语言:javascript
复制
 1#include<stdio.h>
 2void add()
 3{
 4    printf("调用add()函数");
 5}
 6void fun(void(*p)())
 7{
 8    p();    //通过函数地址调用add函数
 9}
10int main()
11{
12    fun(add);//函数地址作为实参
13    return 0;
14}

可以思考下为什么要把一个函数的地址作为参数传递给另一个函数,要知道在C语言中,一个函数内部是可以直接调用其他函数的,既然可以直接调用,为什么还要用这么麻烦的办法去把函数当做参数来传递呢。

上一篇:指针(一)

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程学习基地 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 指针数组
  • 数组指针
  • 二、二级指针
    • 二级指针定义和使用
      • 二级指针和指针数组
      • 三、指针函数和函数指针
        • 指针函数
          • 函数指针
          • 四、和指针有关的传参
          相关产品与服务
          对象存储
          对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档