指针

一、
指针变量:指向地址的变量  
指针就是地址,用来存放地址的变量
变量指针:变量地址
指针是存放地址才出现的,地址是为了标示一块地址空间的。
指针让地址有地方存放,指针让内存的访问更加便捷。
指针的大小子在32位平台是4个字节,在64位平台是8个字节。
二、指针和指针类型
指针是有类型的,类型是:type+*的方式,比如 int* 类型的指针是为了存放 int 类型的地址。
(1)、指针+-整形
#include <stdio.h>
#include <windows.h>
int main()
{
    int num=10;
    char *pc=(char *) &num;
    int *pi=&num;
    printf("%p
",&num);// 0070FE94
    printf("%p
",pc);  // 0070FE94
    printf("%p
",pc+1);// 0070FE95
    printf("%p
",pi);  // 0070FE94
    printf("%p
",pi+1);// 0070FE98
    system("pause");
    return 0;
        
}
 
总结:指针的类型决定了指针行前或者向后走一步有多大(距离)。
(2)、指针的解引用
#include <stdio.h>
#include <windows.h>
 
int main()
{
    int num = 0x11223344;
    char *pc = (char *)&num;
    int *pi = &num;
    *pc = 0x55;
    *pi = 0;
    system("pause");
    return 0;
}
总结:指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字符)
比如:char* 的指针解引用就只能访问一个字节,而int* 的指针的解引用就能访问四个字节。
三、指针数组和数组指针
指针数组:指针数组是数组,是一个存放指针的数组
int *arr1[10];
char *arr2[4];
数组指针:数组指针是指针
int (*p)[10];
数组指针的使用
#include <stdio.h>
#include <windows.h>
 
int main()
{
    int arr[10] = { 0 };
    //arr 表示数组首元素的地址
    //&arr表示数组的地址
    printf("%p
", arr);     //00EFFC3C 
    printf("%p
", arr + 1); //00EFFC40
    printf("%p
", &arr);    //00EFFC3C
    printf("%p
", &arr + 1);//00EFFC64
    system("pause");
    return 0;
}

 

二维数组传参
void
test() {     int arr[3][5];     print(arr); } void print(int arr[][5])//可以 void print(int arr[3][5])//可以 void print(int (*arr)[5])  //推荐 void print(int **arr)   //不推荐 数组传参降级为指针,指向该内部元素的指针。二维数组降级为一维数组是指针。 一级指针传参 #include <stdio.h> #include <windows.h> void test(int *p,int n) {     int i = 0;     for (; i < n; i++)     {        printf("%d ", p[i]);//*(p+i)     } }   int main() {     int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };     int *pt = arr;     int size = sizeof(arr) / sizeof(arr[0]);     test(pt, size);          system("pause");     return 0; }
二级指针传参
#include <stdio.h>
#include <windows.h>
void test(int  **ptr)
{
    printf("num=%d
", **ptr);
}
int main()
{
    int num = 10;
    int *p = &num;
    int **pp = &p;
    test(pp);
    test(&p);
    system("pause");
    return 0;
}
函数指针
     函数指针是指向函数的指针变量,即本质是一个指针变量。
     int (*f)(x,y);
 
指针函数
指针函数是带指针的函数,即本质是一个函数。函数返回类型是某一类型是指针。
        类型标识符   *函数名(参数)
      int *f(x,y);
首先它是一个函数,函数返回值是一个地址值。函数返回值必须用同类型是指针变量来接受,
也就是说,指针函数一定能有函数返回值,而且,在主调函数中,函数返回值必须赋给同类型的指针变量。
表示:
    float *fun();
    float *p;
    p=fun(a);
查看一个月第几周第几天是多少号?
#include <stdio.h>
#include <windows.h>
int *Getdata(int wk,int dy)
{
    static int calendar[5][7]={{1, 2, 3, 4, 5, 6,7},
                               {8, 9,10,11,12,13,14},
                               {15,16,17,18,19,20,21},
                               {22,23,24,25,26,27,28},
                               {29,30,31,-1}};
    return &calendar[wk-1][dy-1];
}
int main()
{
    int wk,dy;
    do
    {
        printf("Enter week(1-5)day(1-7)");
        scanf("%d%d",&wk,&dy);
    }while((wk<1||wk>5)||(dy<1||dy>7));
    printf("%d
",*Getdata(wk,dy));
    system("pause");
    return 0;
}

如何辨别指针函数和函数指针

看函数名前的指针 *号有没有被括号()包含,如果被包含就是函数指针,反之则是指针函数。
函数指针数组
即把函数的地址存放到数组中
int (*parr[10])();
转移表(计算器)
#include <stdio.h>
#include <windows.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 divi(int a,int b)
{
    if(b==0)
    {
        printf("div is zero
");
    }
    else
    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,divi};//转移表
    while(input)
    {
        printf("************************
");
        printf("  1:add         2:sub   
");
        printf("  3:mul         4:divi  
");
        printf("************************
");
        printf("请选择:");
        scanf("%d",&input);
        if((input<=4&&input>=1))
        {
            printf("请输入操作数:");
            scanf("%d%d",&x,&y);
            ret=(*p[input])(x,y) ;
        }
        else
        
            printf("输入有错!
");
            printf("ret=%d
",ret);       
    }
    system("pause");
    return 0;
}
指向函数指针数组的指针
指向函数指针数组的指针是一个指针
指针指向一个数组,数组的元素都是函数指针;
#include <stdio.h>
#include <windows.h>
void test(const char* str)
{
    printf("%s
",str);
}
int main()
{
    void (*pfun)(const char*)=test;//函数指针pfun;
    void (*pfunArr[5])(const char* str);//函数指针数组pfunArr;
    pfunArr[0]=test;
    void (*(*ppfunArr)[5])(const char*)=&pfunArr;//指向函数指针数组的指针ppfunArr;
    system("pause");
    return 0;
}
 
回调函数
       回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
       这有一些大量的示例可以帮助大家理解回调函数https://www.zhihu.com/question/19801131
 
下面几个例子帮助大家理解
#include <stdio.h>
#include <windows.h>
int int_cmp(const void *p1,const void *p2)
{
    return (*(int *)p1>*(int *)p2);
}
void _swap( void *p1,  void *p2, int size)
{
    int i=0;
    for(i=0;i<size;i++)
    {
        char tmp=*((char *)p1+i);
        *((char *)p1+i)=*((char *)p2+i);
        *((char *)p2+i)=tmp;
     }
}
void bubble(void *base,int count,int size,int(*cmp)(void *,void *))//int(*cmp)(void *,void *)回调函数
{
    int i=0;
    int j=0;
    for(;i<count-1;i++)
    {
        for(;j<count-1;j++)
        {
            if(cmp((char*)base+j*size,(char*)base+(j+1)*size)>0)
            {
                _swap((char *)base+j*size,(char*)base+(j+1)*size,size);
            }
         }
    }
}
int main()
{
    int arr[]={5,1,6,2,3,8,4,9,7};
//    char *arr[]={"aaaa","iiii","cccc","bbbb"};
    int i;
    bubble(arr,sizeof(arr)/sizeof(arr[0]),sizeof (int),int_cmp);
    for(i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
    {
        printf("%d ",arr[i]);
    }
    printf("
");
    system("pause");
    return 0;
}
 
 
原文地址:https://www.cnblogs.com/xjq6898/p/7901318.html