对指针的初级认识

1.数组指针 (行指针)(优先级;()>[]>*)
定义:int (*p)[n];
解释:()的 优先级高,首先说明p为一个指针,指向一个整形的一维数组,这个数组的长度为n,也可以称他的步长为n,当执行p+1时,p要跨过n个整形数据的长度。
当把二维数组赋给一指针,方法如下:
int a[3][4];
int(*p)[4];   //该语句定义了 一个一维数组,指向含有四个元素的一维数组。
p = a;            //将二维数组的首地址赋给p,也就是&a或者&a[0][0]。
p++;           //该语句结束后,也就是p=p+1,跨过a[0]行指向a[1]行。
数组指针的简单理解:
(1)首先它是一个指针,它指向一个一个数组,在32位系统下任何类型的指针都占四个字节。至于指向的数组占多少个字节,要看数组的大小,简称“指向数组的指针”。
(2)数组指针只是一个指针变量,用来指向二维数组,它占内存中一个指针的存储空间,

2.指针数组
定义:int *p[n];
[]的优先级高,它先与P结合为一个数组,再由int*说明这是一个整形数组指针,它有n个指针类型的数组元素。
当执行p+1时,指向的是下一个数组元素。这样赋值是错误的:p=a;yinweip是不可知的表示,只存在p[0],p[2]...p[n-1],而且他们指针变量可以用来存放变量地址的。但是可以这样表示:*p=a;*p表示指针数组的第一个元素的值,a的首地址的值。
int a[3][4];
int *p[3];//表示一个数组内存放了三个指针变量,分别为p[0],p[1],p[2]
p++;//表示p数组指向下一个数组元素,(该数组里每一个元素都是一个指针)
 for (i = 0; i < 3; i++)
    p[i] = a[i];
指针数组的理解:
(1)是多个指针变量,一数组的形式存储在内存中,占有多个指针存储空间。
(2)它是一个数组,数组的元素都是指针,数组占多少个字节由数组的本身的大小决定,每个元素都是一个指针,在32位系统下的任何类型指针类型都占四个字节,简称“储存指针的数组”.
举个例子:
A)int*p1[10];
B)   int (*p)[10];
分析:
(优先级:()>[]>*) 
P1:
"[]"的优先级高,p1和“[]"先结和,构成一个数组的定义,数组名为p1,int*修饰的内容是数组的内容,即数组的每个元素,解释为:这是一个数组,其包含了10个指向int*类型数据的指针。
P2:
"()"d额优先级高于"[]","*"和"()"先构成一个指针的定义,指针的变量名为P2,,int修饰数组内容,即数组的每个元素,解释为:它是一个指针,指向包含10个int类型的数据的数组,即数组指针。
3.指针函数
本质:函数指针本质是一个函数,函数返回类型是某一类型的指针。
定义:返回标识符类型  * 返回函数名(形式参数列表)
      {
           函数体
      }
  举例:   int  *(x, y);
解释:首先它是一个函数,只不过这个函数的返回值为一个地址。函数的返回值必须用一个同类型的指针变量来接收,也就是说,指针函数一                定有一个函数返回值。而且在主调函数中,函数值必须赋给同类型扽指针变量。
float *fun();
float *p;
p = fun();
简单理解指针函数:当一个函数声明其返回值为一个指针时,实际上就是返回一个地址给调用函数,以用于需要指针或地址的表达式中。
由于返回的是一个地址,所以类型说明符一般都为int。函数返回的是一个地址值,经常使用在数组的某一地址上。

4.函数指针
本质:函数指针是指向函数的指针变量,即本质是一个指针变量。  指向函数的指针包含了函数的入口地址(即地址),可以通过他们来调用函数。 类似于数组名就是数组的首地址。                                                                                                        
格式:类型说明符 (*函数名) (参数)
其实这里也不能称为函数名,应该叫函数指针变量名。
举例:
  1.  int(*f)(int x);//声明了一个函数指针
     f = func1;//将func1函数的首地址赋给指针
  1. 解释 (*(void(*)())0)(); 
    把0强制类型转换为函数指针类型,具体类型为(void(*)),然后把函数指针解引用就可以把它当作函数使用。
  3.解释 void(*signal(int ,void(*)(int)))(int )
    signal微函数声明,且signal有两个参数,一个为int ,一个为函数指针。该函数指针指向的函数有一个Int参数,返回值为void.
   signal的返回值类型为函数指针,该函数指针指向的函数有一个int参数,返回类型为void.

注意
(1)指针名和指针运算符外边的括号改变了默认的运算符优先级。如果没有圆括号,就变成了一个返回整形指针的函数原型。
(2)函数指针不能做自增和自减操作,否则程序会崩溃。
举例:
void(*p)();
把函数地址赋给函数指针的格式及两种方式:
格式函数指针=[&]函数名;(函数名后不带括号和参数,&可要可不要)
(1)p = &function;
(2)p = function;
解释:取地址运算符&是可有可无的,因为函数的标识符就表示了函数的地址。如果要调用函数,还必须要包含一个圆括号区包含参数列表。
通过指针调用函数的两种方法:
(1)x=(*p)();//可以明确看出是通过指针而非函数名来调用函数的
(2)x=p();
5.回调函数(callback functions)
回调函数:就是通过一个函数指针调用的函数。如果你把函数的指针(地址)作为参数传给另一个函数时,我们就说这是回调函数。回调函数不是由该函数直接实现,而是在特定的事件或发生时由另外的一方调用,用于对该事件或条件进行响应。
举例:练习使用qsort函数排序各种类型的数据。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int int_cmp(const void *p1, const void *p2)
{
        return (*(int*)p1> *(int*)p2);
}
void my_swap(void *p1, void *p2, int size)
{
        int i = 0;
        for (i = 0; i < size;i++)
        {
               char temp = *((char*)p1 + i);
               *((char*)p1 + i) = *((char*)p2 + i);
               *((char*)p2 + i) = temp;
        }
}
void bubble_sort(void *base, int sz, int size, int(*cmp)(void*, void*))
{
        int i = 0;
        int j = 0;
        for (i = 0; i < sz; i++)
        {
               for (j = 0; j < sz - 1; j++)
               {
                       if (cmp((char*)base + j*size, (char*)base + (j + 1)*size)>0)
                       {
                              my_swap((char*)base + j*size, (char*)base + (j + 1)*size, size);//((j+1)*size)表示跳过一个元素
                       }
               }
        }
}
int main(void)
{
        int arr[] = {1,2,3,9,8,7 };
        int sz = sizeof(arr) / sizeof(arr[0]);
        bubble_sort(arr, sz, sizeof(int), int_cmp);
        for (int i = 0; i < sz; i++)
        {
               printf("%d\n", arr[i]);
        }
        system("pause");
        return 0;
}

void bubble_sort(void *base, int sz, int size, int(*cmp)(void*, void*))
1.base是需要排序的的目标数组名或理解为首地址,可以写成&arr[i]
2.sz表示参加排序的元素个数
3.size表示目标数组中元素的字节长度,
4.cmp时自己定义的比较函数。
6.函数指针数组

数组是一个存放想同类型的存储空间。
比如:指针数组(每个元素类型都是指针类型)
int *arr[10];//数组的每个元素都是int*
函数指针数组就是把函数的地址存放到一个数组中去。
举例:
int(*parr1[10])();
解释:parr1先和[]结合成一个数组,说明parr1为数组,数组的类容是int(*)()类型的函数指针。
函数指针数组的应用:表转移


7.指向函数指针数组的指针

指向函数指针数组的指针是一个指针。指针指向一个数组。数组的元素都是函数指针。
如void(*((*parr1)[10]))(void)  解释为:一个指向有10元素,每个元素为指向一个返回值为空的函数组的指针。


void test(const char*str)
{
        printf("%s\n", str);
}
int main()
{
        void(*pfun)(const char*) = test;
        //函数指针pfun
        void(*pfunArr[5])(const char *str);
        pfunArr[0] = test;
        //函数指针数组pfunArr
        void(*(*ppfunArr)[10])(const char*) = &pfunArr;
        //指向函数指针数组pfunAdd的指针ppfunAdd
        return 0;
}




猜你喜欢

转载自blog.csdn.net/qq_40955824/article/details/80473278