指针数组、数组指针、函数指针、指针函数总结
指针数组 && 数组指针
char *a[5]; //定义一个指针数组, 数组的元素都是char *指针类型。初始化也可以在里面存放字符或字符串。a的类型是char *[5] //若char *a[5]={"red","white","blue","dark","green"}; //a在这里的类型是char *[],实质上是一个二级指针。也就是说a所代表的那块内存里面存放着的是数组中第一个元素的地址。 //a+1所代表的那块内存里面存放着的是数组中第二个元素的地址,依此类推…… //a[0]就是“red”字符串的地址,printf("%s",a[0]); //a[0]+1,表示在"red"字符串的地址上偏移一个位置,访问字符'c'.printf("%c",*(a[0]+1)) //若a的地址是0x0000000,则a+1的地址是0x00000008(64位平台)或0x00000004; int (*ptr)[5]; //定义一个指向数组的数组指针ptr,它的实际类型为char (*)[5],(数字可以忽略)因为在有些严格的编译器中不同时会提出警告 再定义一个二维数组int a[1][5]={1,2,3,4,5}; //a的类型为int [1][5](数字可以忽略),列的维度相同,p=a可以赋值。 也就是说此时数组指针ptr可以看做一个二级指针,它的用法跟char **a相同。从上面我们可以看到char (*)[]、 char [][]、char **其实可以看成是等价的
#include <stdio.h> int main(void) { char *a[5]={"red","white","blue","dark","green"}; printf("%s %c %s\n", a[0], *(a[0]+1), a[1]+1); printf("%x %x\n",a[0], a[1]); char m[2][5]={"xxx", "yyyy"}; char (*ptr)[5]=m; printf("%x %s %s %x %s\n", ptr[0], ptr, ptr[1], ptr[0]+2, ptr[0]+1); printf("%d ",sizeof(a)); printf("%d ",sizeof(m)); return 0; }@1 定义指针数组,组中元素均为char *类型
@2 定义数组指针,ptr类型为char (*)[],m类型为char [][],这两类型间是可以赋值的。但他们不是完全等价的。
@3 a的类型为char*[5],sizeof(a)=sizeof(char *)*5;
m的类型为char [][]的二维数组,sizeof(m)求得它在内存中实际所占字节,有些编译器出于效率考虑会对字节进行对齐。
运行结果如下
常见误区
double n =2.0, *pt=&n; printf("double %d %d\n", pt, pt+1);//差为8 char c='m', *q=&c; printf("char %d %d\n", q, q+1);//差为1 char **p=&q; printf("%d %d",p ,p+1);//差为4 printf("%d %d %d",sizeof(int*), sizeof(double*), sizeof(char*), sizeof(int**));//从结果中可以发现,不论什么类型的指针在内存中都是占四个字节的大小存放
函数指针 && 指针函数
函数指针和其它指针一样,对函数指针执行间接访问之前必须把它初始化为指向某个函数。
下面是一种初始化函数指针的方法:
int fun( int );
int ( * pf ) ( int ) = &fun;
创建函数指针pf并将其指向函数fun。在函数指针的初始化之前具有fun的原型是很重要的,否则编译器无法检查fun的类型与pf所指向的类型一致。
初始化声明后,我们可以有以下三种方式调用函数:
int ans;
1) ans = fun( 25 );
2) ans = ( *pf ) ( 25 );
3) ans = pf ( 25 );
语句1简单的使用名字调用函数fun。但它的执行过程可能跟你想的不一样:函数名fun首先被转换为一个函数指针,该指针指向内存中的一块位置。然后,函数调用操作符调用函数,执行开始于这个地址的代码。
语句2对pf执行间接访问操作,将pf转换为函数名。但这种转换其实是不必要的,编译器在执行函数调用操作符之前又会把它转换回去。
语句3和前两条执行效果一样的。
函数指针的常见用途就是把函数指针作为参数传递给函数,下面是例子。
#include <stdio.h> #include <string.h> int compare_int(void const *a, void const *b) { if( *(int *)a == *(int *)b) return 0; else return 1; } int compare_char(void const *a, void const *b) { if(strcmp ((char *)a, (char *)b) == 0) return 0; else return 1; } void Compare(void const *a, void const *b,int (*compare)(void const *, void const *)) { if(compare(a, b) == 0) printf("they are equal\n"); else printf("not equal\n"); } int main(void) { int m=4,n=5; Compare(&m, &n, compare_int); char a[4]="abc",b[4]="abc"; Compare(a, b, compare_char); }
运行结果:
使用以上技巧的函数被称为回调函数(callback function)。用户将一个函数指针作为参数传递给其它函数,后者将“回调”用户的函数。分别为比较整型与字符串编写不同的比较函数compar_int(void const *,void const *)和compar_char(void const *,void const *),通过向Compare(const void *,const void *,int (*compare)(void const *, void const *))传递不同的函数指针,通过同一接口实现对不同类型数据的比较。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。