一文搞懂指针类型

  1. 字符指针
  2. 数组指针
  3. 指针数组
  4. 数组传参和指针传参
  5. 函数指针
  6. 函数指针数组
  7. 指向函数指针数组的指针
  8. 回调函数

  9. 指针复习

    1.指针就是个变量,用来存放地址,地址是唯一标识一块内存空间

    2.指针的大小是固定的4/8个字节(32/64)

    3.指针是有类型的,指针的类型决定了指针的+-整数的步长,指针类型对指针解引用操作权限有多大

    4.指针的运算 指针+-整数; 指针-指针 ; 指针的关系运算 

    5.指针加指针(指针+指针)这是不可以的🙅 毫无意义

1.字符指针 char*

char ch = 'w';

char* pc = &ch;

char  arr[] ="abcdef";
char* p = arr;
char* ps = "abcdef";

2.  指针数组

int main()
{
    char* arr[5];//存放指针的数组,指针数组
    char* arr[5] = {"abcdef","zhangsan","hehe","wangcai","ruhua"};
    //不是把5个字符串放在数组里,而是把首字符地址,存放在数组里去
    int* arr1[10];
    char** arr1[10];
    return 0;
}

3.数组指针  是指针

        指向数组的指针,数组的地址

int arr[10] = {1,2,3,4,5,6,7,8,9};//&arr 取出arr的地址
int (*pa)[10] = &arr;
//指针指向数组 这个数组(10个元素)int类型

3.1 数组名和&数组名

        数组名是首元素地址;&数组名则是 数值的地址;

        从数值的角度他们俩一样 但从类型的角度不同

&arr = 0x013FBB0;
arr  = 0x013FBB0;
//虽然取出的地址都一样 但类型不同
&arr+1 = 0x013FBD8; // 8*16^0+2*16^1 = 40 10个int 
arr+1 = 0x013FBB4;

三种情况

1.sizeof(arr);//在sizeof里的数组名则是 整个数组

2.&arr ;//取地址&arr 则是 整个数组

3.其他情况出现arr数组名则都是 首元素地址 

3.2 数组指针到底有什么用

void print1(int arr[10],int sz)
{
    int i = 0;
    for(i = 0;i<sz; i++)
    {
        printf("%d",arr[i]);
    }
    printf("\n");
}
void print2(int (*p)[10],int sz)
{
    int i = 0;
    for(i = 0; i<sz ;i++)
    {
        printf("%d",(*p)[i]);//*(&arr)
    }
}
int main()
{
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    int sz = sizeof(arr)/sizeof(arr[0]);
    print1(arr,sz);//arr 为首元素地址
    print2(&arr,sz);//把10个整形元素的数组传过来
    return 0;
}

数值指针在一维数组中用的少,在二维数组中比较常见;

int arr[3][5] = {{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7}};
print3(arr,3,5);
print3(int arr[3][5], int r; int c)
{
    int i = 0;
    for(i = 0; i<r;i++)
    {
        int j =0;
        for(j = 0;j<c;j++)
        {
            printf("%d",arr[i][j]);
        }
        printf("\n");
    }
}
print4(&arr,3,5);
void print4(int(*p)[5],int r, int c)
{
    int i = 0;
    for(i = 0; i<r;i++)
    {
        int j =0;
        for(j = 0;j<c;j++)
        {
            printf("%d",*(*(p+i)+j));
        }
    }
   
}

在二维数组中,arr为首元素地址,二维数组的首元素地址就是二维数组的第一行

arr是二维数组的数组名,

*(p+i) ==  p[i] 等价于 

4. 数组传参和指针传参

4.1 数组传参

        一维数组传参

        *数组传参 形参 可以是数组也可以是指针

int arr[10] = {0};
test(arr);

1.test(int arr[]) //ok
2.test(int arr[10]) //ok

3.test(int* arr) // ok
------------------------
int *arr2[20] = {0}; //指针数组 int(*)[20] 20个int*类型元素
test2(arr2);

1.test(int* arr2[20]);
2.test(int** arr);

二维数组传参  

总结:二维数组只能省略

int arr[3][5] {0};
test(arr);

1.test(int arr[3][5]); ok
2.test(int arr[][]); no
3.test(int arr[][5]); ok 可以省略行

4.test(int* arr);arr是一行 的地址
5.test(int* arr[5]); no
6.test(int(*arr)[5]); ok
7.test(int** arr);no

4.2 指针传参

        一级指针传参 

int arr[10] = {1,2,3,4,5,6,7,8,9};
int* p = arr;
int sz = sizeof(arr)/sizeof(arr[0]);
//一级指针p: 传给函数
print(p,sz)
void print(int* p ,int sz)
//当一个函数参数部分为一级指针的时候,函数能接收什么函数呢?
void test(int* p)
{}

int a = 0;
test(&a); //ok 

int *ptr = &a;
test(ptr); //ok

int arr[10];
test(arr); //ok


二级指针传参

#include <stdio.h>
void test(int** ptr) 
{
 printf("num = %d\n", **ptr); 
}
int main()
{
 int n = 10;
 int*p = &n;
 int **pp = &p;
 test(pp);
 test(&p);
 return 0; 
}

5.函数指针

        指向函数的指针 

int Add(int x, int y)
{
    return x+y;
}
int main()
{
    int arr[10] = {0};
    printf("%p\n",&arr); //    取出数组的地址;
    printf("%p\n",Add); // 相同 都是函数的地址
    printf("%p\n",&Add); // Add 和&Add 一样

    int(*pf)(int x, int y) = &Add; // int (*)(int , int)
    int sum = (*pf)(3,5); //
    printf("%d\n",sum);

    int sum = Add(3,5);
    int sum = pf(3,5);
}

        函数指针数组 

        是数组 一种存储函数指针的数组

int* p;//整形指针
int* arr[5];//整形指针数组
int(*pf)(int,int);//函数指针

int(*pfArr[4])(int,int);//函数指针数组
int (*)(int,int);
pfArr[4];
//可以存放多个参数相同,返回类型相同的函数的地址;

//函数指针数组的用途:转移表
#include <stdio.h>
int add(int a, int b)
{
           
    return a + b;
    
}
int sub(int a, int b)
{
           
    return a - b;
    
}
int mul(int a, int b)
{
           
    return a*b;
    
}
int div(int a, int b)
{
           
    return a / b;
    
}
int main()
{
     int x, y;
     int input = 1;
     int ret = 0;
     int(*p[5])(int x, int y) = { 0, add, sub, mul, div }; //转移表
     while (input)
     {
          printf( "*************************\n" );
          printf( " 1:add           2:sub \n" );
          printf( " 3:mul           4:div \n" );
          printf( "*************************\n" );
          printf( "请选择:" );
      scanf( "%d", &input);
          if ((input <= 4 && input >= 1))
         {
          printf( "输入操作数:" );
              scanf( "%d %d", &x, &y);
              ret = (*p[input])(x, y);
         }
          else
               printf( "输入有误\n" );
          printf( "ret = %d\n", ret);
     }
      return 0; 
}

指向函数指针数组的指针 

是一种指针 指向函数指针数组的指针

//函数指针
int (*pf)(int x, int y);
//函数指针数组
int (*pfArr[5])(int x, int y);
pfArr[5] int(*)(int , int );
//指向函数指针数组的指针
int (*(*pfArr)[5])(int x, int y);

回调函数

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

说人话就是函数调用别的函数来实现功能 详情请看qsort函数的模拟实现

总结

以上就是本文的全部内容啦 作为C的灵魂---指针 原来有这么多种类型 看到这里了还不来一个一键三连吗 你的点赞是我创作的动力QAQ

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值