• 指针数组、数组指针、函数指针、指针函数总结


    指针数组 && 数组指针

    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
    ", a[0], *(a[0]+1), a[1]+1);
        printf("%x    %x
    ",a[0], a[1]);
        char m[2][5]={"xxx", "yyyy"};
        char (*ptr)[5]=m;
        printf("%x    %s    %s    %x    %s
    ", 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
    ", pt, pt+1);//差为8
        
    char c='m', *q=&c;
    printf("char %d %d
    ", 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
    ");
    	else
    		printf("not equal
    ");
    }
    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 *))传递不同的函数指针,通过同一接口实现对不同类型数据的比較。


           指针函数,指针函数是指带指针的函数。即本质是一个函数。函数都有返回类型(假设没有返回值,则为无值型),仅仅只是指针函数返回类型是某一类型的指针。
  • 相关阅读:
    JDBC
    MySQL 事务
    MySQL 处理海量数据时一些优化查询速度方法
    MySQL 分支和循环结构
    MySQL 分页查询和存储过程
    Oracle PL/SQL异常、存储过程和触发器
    Oracle PL/SQL游标
    mysql主键问题
    spring-springmvc code-based
    AOP实现原理
  • 原文地址:https://www.cnblogs.com/cynchanpin/p/7396730.html
Copyright © 2020-2023  润新知