指针的一些汇总

本文深入探讨C语言中的指针概念,包括函数指针的定义与使用,数组指针的类型与操作,以及多级指针的解析。通过实例展示了如何传递数组、函数地址以及如何实现回调函数。此外,还讨论了void*指针的特性及其在类型转换中的作用。
摘要由CSDN通过智能技术生成

程序源码

#include <stdio.h>

#if 1
int add(int x,int y)
{
    return (x+y);
}
int main()
{
   //字符指针--指向字符的指针
    char ch1 = 'w';
    char *p = &ch1;
    const char *p2 = "abcdef";//p2存放字符a的地址

    //指针数组-存放指针的数组
    int *arr[10];
    char *ch2[5];

    //数组指针--指向数组的指针
    int arr2[5];  //数组
    int (*pa)[5] = &arr2;
    //取数组的地址,pa是一个数组指针(去掉名字(pa),就是其类型:int(*)[5],指向数组的指针类型)

    //函数指针--指向函数的指针
    int (*padd)(int,int) = add;  //定义并指向,函数指针指向返回值为int,有两个形参都为int的函数
    //int sum = (*padd)(1,3);  //ok,调用1
    int sum = padd(1,3);       //ok,调用2
    printf("sum = %d\n",sum);

    //函数指针数组--数组存放的是函数指针,也是函数地址
    int (*parr1[5])(int,int);   //定义

    //指向函数指针数组的指针
    int (*(*pparr)[5])(int,int) = &parr1;  //定义

    return 0;
}   
#endif
#if 1
 //关于传参部分

#include <stdio.h>

int main()
{
    //1维数组的传参
    void test1(int arr1[])  //ok
    {
    }
    void test2(int arr1[10]) //ok,
    {
        // 10写不写都可以
    }
    {
    void test3(int *arr1)//ok,
    {
    //  指针和数组名大多数可以互换使用,
    //  不同是数组名是常量,指针是变量
    }
    
    void test4(int *arr2[20])  //ok.20可省
    {
    }
    void test5(int **arr2)//ok,
    {
    //arr2是一个指针数组,数组名是首元素的地址,也是指针的地址,
    //存放一级指针的地址,参数就可以设为2级指针
    
    }
    int arr1[10] = {0};   //1维数组
    int *arr2[20] = {0}; //指针数组--存放指针(地址)的数组
    test1(arr1);
    test5(arr2);
    return 0;
    }
}
#endif

#if 1
 //2维数组传参

#include <stdio.h>

int main()
{
    void test1(int arr[3][5])//ok
    {
        //保险做法
    }
    void test2(int arr[][5])//ok
    {
        //2维数组必须指明列数
    }
    void test3(int arr[3][]) //err
    {
    }
    void test4(int arr[][]) //err
    {
    }
    void test5(int *arr)  //err
    {
    	//int *arr表示指针arr存放的int类型的地址
    	//而2维数组名arr不是存放int的地址,它是存放1维数组的地址
    }
    void test6(int **arr)//err
    {
        //数组的地址不能放在2级指针里
        //2级指针是用来存放1级指针变量的地址
        //而2维数组名arr是存放1维数组的地址  
    }
    void test7(int (*arr)[5])  //ok
    {
        //数组指针--指针指向一个1维数组,即指针变量arr存放1维数组的地址
    }

    int arr[3][5]={0};
    test1(arr);   //2维数组传参,行指针

    return 0;
}
#endif
#if 1
 //一级指针传参

#include <stdio.h>

int main()
{
    void test1(int *p)   //需传int类型变量的地址
    {
    }
    void test2(char *p)
    {
    }
    
    int a = 10;
    int *p1 = &a;
    test1(&a);
    test1(p1);

    char ch = 'w';
    char *pc = &ch;
    test2(&ch);
    test2(pc);

    return 0;
}
#endif
#if 1
//二级指针传参

#include <stdio.h>

int main()
{
    void test(int **p)  //二级指针存放一级指针变量的地址
    {
    }
    int *ptr;
    int **pp = &ptr;
    test(&ptr);
    test(pp);

    int *arr[10];
    test(arr);   //指针数组也可以,数组名就是首元素的地址,也就是一级指针的地址

    return 0;
}
#endif
#if 0
//函数指针--指向函数的指针-存放函数地址的指针

#include <stdio.h>

int main()
{
    int add(int x,int y)
    {
        return (x+y);
    }
    
    int a = 10;
    int b = 20;
    printf("%d\n",add(a,b));  //30
    
    //&add与add都是函数的地址
    printf("%p\n",&add);   //打印函数的地址:0x4004c4
    printf("%p\n",add);    //打印函数的地址:0x4004c4
    printf("%p\n","qwer"); //x400750,说明了对常量取地址无意义
    printf("%p\n",&"qwer"); //x400750
    
    int (*pa)(int,int) = add;  //定义函数指针,指针指向函数,函数的返回值为int,两个形参都为int  
  //调用,说明*写不写都可以,最好写第2种
    printf( "%d\n",pa(2,3));      //5
    printf( "%d\n",(*pa)(2,3));   //5
    printf( "%d\n",(**pa)(2,3));  //5
    printf( "%d\n",(***pa)(2,3)); //5
    return 0;
}
#endif
#if 0
 //函数指针

#include <stdio.h>

int main()
{
    void print(char *str)
    {
        printf("%s\n",str);
    }
    void (*p)(char *) = print;

    (*p)("Hello"); //等价于printf("Hello\n");
    return 0;
}
#endif

#if 1
//函数指针分析

#include <stdio.h>

int main()
{
    //代码1
    (*(void(*)())0)();
    //void(*)()-函数指针类型
    //把0强制类型转换成:void(*)()
    //0就是一个函数的地址了
	//通过*,调用0地址处的函数,此函数无参,返回值void

    //代码2
    void (*signal(int,void(*)(int)))(int);
    //这是一个函数声明
    //函数名:signal
    //参数1:int
    //参数2:void(*)(int) //函数指针
    //返回值:void(*)(int)//把函数名和参数去掉可得
    
    //类型重定义
    typedef unsigned int uint;//将unsigned int类型重定义为uint
    typedef void(* pfun_t)(int);//将void (*)(int)类型重定义为pfun_t
    
    //简化代码2
    pfun_t signal(int,pfun_t);//函数声明时可以不写形参
    return 0;
}
#endif
#if 0
//函数指针数组--把函数的地址存到一个数组中

#include <stdio.h>

int main()
{
    int add(int x,int y)
    {
        return x+y;
    }
    int sub(int x,int y)
    {
        return x-y;
    }
    int mul(int x,int y)
    {
        return x*y;
    }
    int div(int x,int y)
    {
        return x/y;
    }
    //定义函数指针数组并初始化,数组元素的类型时int (*)(int,int),函数指针
    int (*parr[4])(int,int) = {add,sub,mul,div};

    int i = 0;
    for(i=0;i<4;i++)
    {
        printf("%d\n",(*parr[i])(2,3));  //5 -1 6 0
     // printf("%d\n",parr[i](2,3));     //5 -1 6 0
    }
    return 0;
}
#endif
#if 0
//函数指针的数组定义
#include <stdio.h>
int main
{
    int (*parr1[10])();   //ok
    /* parr1先和[]结合,说明parr1是数组,
   	数组有10个元素是int (*)()类型的函数指针
    */
    int *parr2[10]();//err,胡写

    int (*)() parr3[10];//err

    return 0;
}
#if 1
//ex
#include <stdio.h>

int main()
{
    char *my_strcpy(char *dest,const char *src)
    {
    }
    //写一个函数指针pf,能够指向my_strcpy
    char* (*pf)(char*,const char*) = my_strcpy;
    
    //写一个函数指针数组pfarr,能够存放4个my_strcpy函数的地址
    char* (*pfarr[4])(char*,const char*)={my_strcpy,my_strcpy,my_strcpy,my_strcpy};
    return 0;
}
#endif

#if 0
#include <stdio.h>

int add(int x,int y)
{
    return x+y;
}
int main()
{
    int arr[10] = {0};
    int (*p)[10] = &arr;  //数组指针--指针指向数组
    int (*pfarr[4])(int,int) = {add};//函数指针数组--数组存放函数指针(地址)
  
    //ppfarr是一个指向函数指针数组的指针,
    //指针指向的数组有4个元素
    //指向的数组的每个元素的类型是一个函数指针int(*)(int,int)
    int  (*(*ppfarr)[4])(int,int) = &pfarr;
    return 0;
}
#endif
#if 1
//回调函数
//回调函数就是一个通过函数指针调用的函数,

#include <stdio.h>

void print(char *str)
{
    printf("hehe:%s\n",str);
}
void test(void (*p)(char*))
{
    printf("test\n");
    p("bit");
}
int main()
{
    test(print); 
/*
输出:test
	 hehe:bit
*/
    return 0;
}
#endif

#if 1
 //void *类型的指针,可以接收任意类型的地址
 //void *类型的指针,不能进行解引用操作
 //void *类型的指针,不能进行+-整数的操作

#include <stdio.h>

int main()
{
    int a = 10;
    int *pa = &a;   
    char *pc = &a;   //w

    void *p = &a;   //ok
    //*p = 0;  //err,解引用后不知道访问多少个字节
    p++;  //err,不知道类型,所以不知道加多少字节

    return 0;
}

#endif

//指针减法1
#include <stdio.h>

int main()
{
    int a[]={1,2,3,4,5,6,7,8,9};
    int i = 0;
    int n =sizeof(a)/sizeof(a[0]);

    int *p = a+n-1;  //指向数组最后一个元素

    for(i=0;i<n;i++) 
    {   
        printf("%d,",*p);    //数组元素逆序输出
        p--; //指向数组前一个元素
    }   
     putchar('\n');

    return 0;
}
//指向同一数组的指针变量相减得到的是数组下标的差值
#include <stdio.h>

int main()
{
    int a[] = {1,2,3,4,5,6,7,8,9};
    int *p2 = &a[2];  //第3个元素地址
    int *p1 = &a[1];
    int *p0 = &a[0];
    printf("p0 = %p, p1 = %p,  p2 = %p\n",p0,p1,p2);

    int n0 = p2 - p0;          //n0 = 2
    int n3 = (int)p2 - (int)p0;//n3 = 8

    int n1 = p2 - p1;//n1 = 1
/*  因为p2和p1不是整型的,所以会有warning,
 *  又p2和p1是指向同一个数组的,所以相减得到指针所指元素位置的差值(是整型的)
 *  p2和p1中存的是数组元素(4个字节)的地址,而不是一个字节的地址,所以结果是1
 *  */
    int n2 = (int)p2 - (int)p1;//n2 =4
    printf("n0 = %d,  n3 = %d\n",n0,n3);
    printf("n1 = %d,  n2 = %d\n",n1,n2);

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

⁽⁽ଘ晴空万里ଓ⁾⁾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值