指针常量/常量指针 数组指针/指针数组 函数指针/指针函数 返回函数指针的函数/返回数组指针的函数

        C语言中有各种比较纠结的结构,容易混淆,也经常说是面试的重点,现在就来总结下各种小纠结;


指针常量和常量指针

        要想搞清楚这一对,必须先知道const关键字;const关键字用来修饰一个变量,表示该变量是只读变量,不可以修改的;(在C语言中const修饰的变量是可以用指针来强制改变的,但在C++中是不行的;)
        顺便说下const的几个作用:
        1、修饰变量为只读,能对不想修改的变量进行保护作用, 能提高程序的健壮性
        2、const定义的常量编译器可以对其进行数据静态类型安全检查;
        3、const修饰函数形式参数:当输入参数为用户自定义类型和抽象数据类型时,将“值传递”改为“const&传递”可以提高效率;
        4、 关键字const的作用是为给读你代码的人传达非常有用的信息。

        指针常量:(int* const  p)指针是常量,指针指向不可以改变,内容可以改变;
        常量指针:(int const *p)指向常量的指针,指向可以改变,但内容不可以改变;
        总结:看const修饰的是指针还是变量;

数组指针和指针数组

        数组指针:表示指向数组的指针,一般就是说二维数组指针;表示为:int  (*ap)[11];
        指针数组:表示数组中存放的都是指针;表示为:int ×  array[11];
演示代码:
 #include<stdio.h>
 
 int main()
 {
     int i, j;
 
 /*********指针数组*********/   
     char* array[3];
     array[0] = "yu";
     array[1] = "zhi";
     array[2] = "hui";
 
     printf("char* array:%s %s %s\n", array[0], array[1], array[2]);
 
 /*********数组指针*************/
     int intArray[3][3] = { 
         {1,2,3},
         {11,12,13},
         {21,22,23}
     };  
 
     int (*ap)[3] = intArray;
     for (i = 0; i < 3; i++)
         for (j = 0; j < 3; j++)
             printf("(ap+%d)[%d]:%d\n", i, j, (*(ap+i))[j]);
 
     return 0;
 }

函数指针和指针函数

        函数指针:指向函数的指针;表示:int  (*func)(int);
        指针函数:返回指针的函数;表示: int*  func(int);
演示代码:
 #include<stdio.h>

 // 指针函数
 int* test(int *tmp)
 {
     *tmp += 10; 
     return tmp;
 }
 
 void test1(int i)
 {
     printf("int test1 i is:%d\n", i); 
 }
 
 void test2(int i)
 {
     printf("int test2 i is:%d\n", i); 
 }
 
 int main(void)
 {
     int tmp = 10; 
     printf("tmp:%d\n", (*test(&tmp)));

 // 函数指针,指向函数的指针
     void (*p)(int) = test1;
     (*p)(110);
 
     p = test2;
     p(119);
 
     return 0;
 }
        额外的总结下函数指针的一些问题:
        在《C陷阱和缺陷》一书中有提到一个问题:在某微处理器上,当计算机启动时,硬件调用首地址为0位置上的子例程;
        最终设计的语句是:(*  (  void (*)()  )  0 ) ();看着挺复杂的,其实还是很简单的,书上也对此进行了详细的说明;这里就大概说下吧:
        首先是构造一个函数指针:void (*)();其中省略了函数名(不习惯的话,可以随意添加一个),不传入参数,无返回值;
        然后把0强制转换为该函数指针,一定要记住:其实函数指针以及函数都是个地址而已,表示从哪个地址入口开始执行;这里强制转换和变量的强制转换一样的:( void (*)() )0;此时的函数指针就是执行 0地址处;
       最后是调用该函数指针,调用一个函数指针,一般是这样:(*func)(),这是标准的调用语句;也可以简写为:func();所以最后调用下该函数指针:(* (void (*)())0)();

返回函数指针的函数

        返回函数指针的函数,最典型的就是 signal()函数;可以参考下:http://blog.csdn.net/yuzhihui_no1/article/details/44748585
        其实这个函数:void  (*signal(int signo, void (*func)(int) ) ) (int);如果不借用typedef  我还真不知道怎么实现它,主要是函数头不知道该怎么写;下面看下我利用typedef来实现的返回函数指针的函数:
 #include<stdio.h>
 
 int test(int i)
 {
     printf("in test!  i = %d\n", i); 
     return i;
 }
 
 typedef int (*func)(int);
 
 func test1(int i)
 {
     int (*p)(int) = test;
     printf("ret test! i = %d\n",(*p)(i));
 
     return p;
 }
     
 int main(void)
 {
     test1(1)(100);
     return 0;
 }
运行结果:

   

返回数组指针的函数

        返回数组的函数是什么样子?我开始绕进去了,后来仔细想了下,那不就是返回指针的函数嘛。哈哈,现在来看下返回数组指针的函数,其实就是返回个二维数组指针;
        返回数组指针的函数:返回一个指向二维数组的指针;表示为:int (*func(int  i)) [4]{};
演示代码
#include<stdio.h>
#include<stdlib.h>
 
 // int (*array)[4];
 
 int (*func(int count))[4]
 {
     int (*array)[4] = malloc(4*sizeof(int));
     (*array)[0] = count*1;
     (*array)[1] = count*10;
     (*(array+1))[0] = count*100;
     (*(array+1))[1] = count*1000;
     return array;
 }
 
 int main()
 {
     int (*tmp)[4] = func(1);
     printf("array[00]:%d\n", (*tmp)[0]);
     printf("array[01]:%d\n", (*tmp)[1]);
     printf("array[10]:%d\n", (*(1+tmp))[0]);
     printf("array[11]:%d\n", (*(1+tmp))[1]);
     free (tmp);
     //free (array);
     return 0;
 }
运行结果:


函数指针数组

        函数指针数组:数组里面存放的都是函数指针;表示为:int (*array[3])(int);
        函数指针数组在系统设计中还是比较容易用到的,其实就是把几个函数指针存放到数组中,方便后面调用;
演示代码:
 #include<stdio.h>
 
 void test(int i)
 {
      i *= 1;
      printf("int test i is:%d\n", i);
 }
 
 void test1(int i)
 {
     i *= 10; 
     printf("int test1 i is:%d\n", i); 
 }
 
 void test2(int i)
 {
     i *= 100;
     printf("int test2 i is:%d\n", i); 
 }
 
 void test3(int i)
 {
     i *= 1000;
     printf("int test3 i is:%d\n", i); 
 }
 
 int main(void)
 {
     void (*func[4])(int) = 
     {   
         test,
         test1,
         test2,
         test3
     };  
     (*func[0])(1);
     (*func[1])(1);
     (*func[2])(1);
     (*func[3])(1);
 
     return 0;
 }
运行结果:
        

        转载请注明作者和原文出处,原文地址: http://blog.csdn.net/yuzhihui_no1/article/details/44748585
       若有不正确之处,望大家指正,共同学习!谢谢!!!

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值