Z :彻底了解指针数组,数组指针以及函数指针 [复

时间:2021-12-28 00:07:58

原创 :彻底了解指针数组,数组指针以及函数指针 [复制链接]

00
帖子
60
主题
16
精华
0
可用积分
74
专家积分
0
在线时间
0 小时
注册时间
2003-10-07
最后登录
2004-12-06
论坛徽章:
0
 
电梯直达Z :彻底了解指针数组,数组指针以及函数指针 [复

1[收藏(0)][报告]

 
Z :彻底了解指针数组,数组指针以及函数指针 [复 发表于 2004-07-30 19:23:41 |只看该作者 |倒序浏览
小弟是一个软件工程师,做unix c/c++ java的开发,每次碰到问题都跑到CU里问人,呵呵,昨天在碰到一个指针数组的问题的时候,由于好久没用,感觉有些陌生了,所以今天归纳总结了一下,希望以后的朋友可以少走些弯路,也不知道对大家有没有用处:) 
一 :关于指针和堆的内存分配 
(1) 指针数组 : 一个数组里放的都是指针,我们把他叫做指针数组:) 
int * a[10]; 由于它是一个数组,他是不能从堆空间里申请空间的。 
只能做个循环,每个元素去申请空间,或者每个元素去指向另外的地址空间。     
( 2 ) 数组指针 : 一个指向一唯或者多唯数组的指针; 
int * b=new int[10]; 指向一唯数组的指针b ; 
a 指向了一个栈空间中10个并排放置的 int 型元素的首地址 
int (*b2)[10]=new int[10][10]; 注意,这里的b2指向了一个二唯int型数组的首地址. 
注意,这里的b2的类型是int (*) ,这样表示一个指向二唯数组的指针。再注意,如果这样在堆空间里已经申请了内存,在释放内存的时候要保证每个空间都要释放。 
int (**b3)[2]=new (int(*)[2])[2]; b3表示一个指向(指向二唯数组的指针)的指针,我们在给他申请空间的时候一定要注意它的类型:它是int (*)型的指针,那申请空间的时候的类型为int(*)[元素个数],由于它后边还带个二唯数组每元的个数后缀,所以加上这个后缀就OK了。 
int (**b4)[2];表示每一个元素都指向(指向二唯数组的指针)的数组。 
由于它是数组,所以要是在堆里申请内存,就必须为每一个元素单独申请。 
b4[0]=new (int(*)[2])[2];原理同上

(3) 指向了一个(指向指针的指针) 
    int ** cc=new (int*)[10]; 
        这种声明很简单因为cc的类型是int*型的指针,所以你要在堆里申请的话就要用(int *)来申请; 
(4) 多唯指针数组的指针数组。 
   int ** d[2];表示一个指向指针的指针数组;数组里有两个元素,每一个元素都是一个指针,这个指针指向另一个指针:) 
   再怎么变也是数组呀,呵呵, 
   如果你读懂了上边的,那下边的声明就很简单了: 
   d[0]=new (int *)[10]; 
   d[1]=new (int * )[10]; 
---------------------------------------

总结 : 只要知道了其中的指针类型,声明一个指针就很简单了,堆里申请稍微复杂点,不过知道了类型,也就稍微烦琐一点。 
  (1)int*ptr;//指针所指向的类型是int

  (2)char*ptr;//指针所指向的的类型是char

  (3)int**ptr;//指针所指向的的类型是int*

  (4)int(*ptr)[3];//指针所指向的的类型是int()[3]

二 : 函数指针 

关于函数指针,我想在我们可能需要写个函数,这个函数体内要调用另一个函数,可是由于项目的进度有限,我们不知道要调用什么样的函数,这个时候可能就需要一个函数指针;

int a();这个一个函数的声明; 
ing (*b)();这是一个函数指针的声明; 
让我们来分析一下,左边圆括弧中的星号是函数指针声明的关键。另外两个元素是函数的返回类型(void)和由边圆括弧中的入口参数(本例中参数是空)。注意本例中还没有创建指针变量-只是声明了变量类型。目前可以用这个变量类型来创建类型定义名及用sizeof表达式获得函数指针的大小: 
unsigned psize = sizeof (int (*) ()); 获得函数指针的大小 
// 为函数指针声明类型定义 
typedef int (*PFUNC) ();

PFUNC是一个函数指针,它指向的函数没有输入参数,返回int。使用这个类型定义名可以隐藏复杂的函数指针语法,就我本人强烈建议我们大内弟子使用这种方式来定义;

下面是一个例子,一个简单函数指针的回调(在GNU编译器上通过,在VC上需要改变一个头文件就OK了)

#include<iostream>;              //GNU 编译器 g++ 实现 
using namespace std; 
/*                              //vc 的实现 
#include "stdafx.h" 
#include <iostream.h>; 
*/

#define DF(F) int F(){  cout<<"this is in function "<<#F<<endl;\ 
       return 0;       \ 

//声明定义DF(F)替代 int F();函数; 
DF(a); DF(b); DF(c); DF(d); DF(e); DF(f); DF(g); DF(h); DF(i);     //声明定义函数 a b c d e f g h i

// int (*pfunc)();              //一个简单函数指针的声明 
typedef int(*FUNC)();   //一个函数指针类型的声明

FUNC ff[] = {a,b,c,d,e,f,g,h,i};   //声明一个函数指针数组,并初始化为以上声明的a,b,c,d,e,f,g,h,i函数

FUNC func3(FUNC vv){    //定义函数func3,传入一个函数指针,并且返回一个同样类型的函数指针 
       vv(); 
       return vv; 
}

/*FUNC func4(int (*vv)()){      //func3的另一种实现 
       vv(); 
       return vv; 
}*/

int main(){ 
       for(int i=0;i<sizeof(ff)/sizeof (FUNC);i++){  //循环调用函数指针 
               FUNC r=func3(ff[ i ]); 
               cout<<r()<<endl;                //输出返回值,只是返回了0 
       } 
       return 0; 

到目前为止,我们只讨论了函数指针及回调而没有去注意ANSI C/C++的编译器规范。许多编译器有几种调用规范。如在Visual C++中,可以在函数类型前加_cdecl,_stdcall或者_pascal来表示其调用规范(默认为_cdecl)。C++ Builder也支持_fastcall调用规范。调用规范影响编译器产生的给定函数名,参数传递的顺序(从右到左或从左到右),堆栈清理责任(调用者或者被调用者)以及参数传递机制(堆栈,CPU寄存器等)。 
好了,先到此为止吧,写这篇文章耗费了基本上快半天的时间了,很多事情还没有做,等改天有时间再回来整理。

   还有很复杂的声明可能也是一种挑战 比如<<Think in c++>;>;里的 
int (*(*f4())[10]();的声明,f4是一个返回指针的函数,该指针指向了含有10个函数指针的数组,这些函数返回整形值;不是这个函数有特别之处,而是Bruce Eckel 说的“从右到左的辨认规则”是一种很好的方法,值得我们去学习,感谢他:)

最后我想应该跟大家说一下,写程序应该就象我的一个朋友所说的:简单就是美;我们应该遵循一个原则 : KISS (Keep It Simple,Stupid ,尽量保持程序简单 出自 :《Practical C programming》),把自己的程序尽量的简单明了,这是个非常非常好的习惯。

由于写的匆忙,可能其中有遗漏的地方,大家发现希望能指正:) 
GOOD LUCK !

Z :彻底了解指针数组,数组指针以及函数指针 [复的更多相关文章

  1. 深入理解C语言中的指针与数组之指针篇

    转载于http://blog.csdn.net/hinyunsin/article/details/6662851     前言 其实很早就想要写一篇关于指针和数组的文章,毕竟可以认为这是C语言的根本 ...

  2. C语言指针与数组的定义与声明易错分析

    部分摘自<C语言深度解剖> 1.定义为数组,声明为指针 在文件1中定义: char a[100]; 在文件2中声明: extern char *a; //这样是错误的 这里的extern告 ...

  3. 深入理解C语言中的指针与数组之指针篇(转载)

    前言 其实很早就想要写一篇关于指针和数组的文章,毕竟可以认为这是C语言的根本所在.相信,任意一家公司如果想要考察一个人对C语言的理解,指针和数组绝对是必考的一部分. 但是之前一方面之前一直在忙各种事情 ...

  4. &lbrack;C&plus;&plus;&rsqb;数组指针,数组引用,函数指针

    数组指针是指一个指向数组的指针,例如有一个数组指针p指向一个数组a[],则 *p是取到这个数组,也就是说 *p=a,因此 **p =a[0], 它的定义为: ]; ]=&a; (*c)表示它是 ...

  5. c语言&period;函数指针数组

    函数指针: 一个指向函数的指针.一般用函数名表示. 函数指针数组:元素为函数指针的数组.转移表.c语言中函数不可以定义为数组,只能通过定义函数指针来操作. #include<stdio.h&gt ...

  6. 转:函数指针数组的妙用&lpar;I&rpar;

    转自:http://blog.sina.com.cn/s/blog_4c78b35f010008hi.html 笔者在开发某软件过程中遇到这样一个问题,前级模块传给我二进制数据,输入参数为 char* ...

  7. 指针数组,数组指针,函数指针,main函数实质,二重指针,函数指针作为參数,泛型函数

     1.指针数组 数组里面的每一个元素都是指针. 指针数组的案比例如以下: 易犯错误: 2.数组指针 归根结底还是指针,仅仅是取*的时候可以取出一整个数组出来. 数组指针:(一个指针指向了数组.一般 ...

  8. C&plus;&plus;中的指针、数组指针与指针数组、函数指针与指针函数

    C++中的指针.数组指针与指针数组.函数指针与指针函数 本文从刚開始学习的人的角度,深入浅出地具体解释什么是指针.怎样使用指针.怎样定义指针.怎样定义数组指针和函数指针.并给出相应的实例演示.接着,差 ...

  9. C语言函数指针的用法

    函数指针是一种在C.C++.D语言.其他类 C 语言和Fortran 2003中的指针.函数指针可以像一般函数一样,用于调用函数.传递参数.在如 C 这样的语言中,通过提供一个简单的选取.执行函数的方 ...

  10. 函数指针 如:void &lpar;&ast;oper&rpar;&lpar;ChainBinTreee &ast;p&rpar;

    在C语言中,一个函数总是占用一段连续的内存区,而函数名就是该函数所占内存区的首地址.我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使该指针变量指向该函数.然后通过指针变量就可以找到并调用 ...

随机推荐

  1. CSS常用选择器名

    一.页面结构划分 box 盒子wrap 包裹container 容器 header 头部main 主要区域footer 底部 content 内容区域banner 横幅广告区域menu 菜单 二.模块 ...

  2. easyUI学习笔记之tab组件的鼠标事件

    一.鼠标经过组件后的事件,自动打开选项卡内容 var tabs = $('#tt').tabs().tabs('tabs'); for(var i=0; i<tabs.length; i++){ ...

  3. 网络编程:socket--python核心编程&lpar;3&rpar;&comma;chapter 1

    最近两天把第一部分的网络编程socket好好学习了一番,收获也蛮多的... 套接字:能使运行在不同或相同计算机上运行的进行通信:套接字一种是基于文件的(同一台计算机进程间通信),另一种是基于网络的(同 ...

  4. &lbrack;cocos2dx&rsqb;2&period;2到3&period;1&lpar;3&period;0&rpar;升级帮助

    摘要: cocos2dx 是一款优秀的多平台,专为2D游戏设计的引擎. 在活跃的开源社区的推进下, 越发稳定和强大. 2.x -> 3.x的更新幅度很大, 性能的提升和功能的丰富也非常明显. 但 ...

  5. HDU 4121 Xiangqi (算是模拟吧)

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4121 题意:中国象棋对决,黑棋只有一个将,红棋有一个帅和不定个车 马 炮冰给定位置,这时当黑棋走,问你黑 ...

  6. 用scikit-learn学习LDA主题模型

    在LDA模型原理篇我们总结了LDA主题模型的原理,这里我们就从应用的角度来使用scikit-learn来学习LDA主题模型.除了scikit-learn,  还有spark MLlib和gensim库 ...

  7. go语言实现无限极分类

     // 应用分类二级菜单     AppCateNode struct {         Id int64 `json:"id"`         Name string `js ...

  8. &lbrack;转帖&rsqb;创建文件或修改文件时间 touch

    Linux命令(五)创建文件或修改文件时间 touch https://www.cnblogs.com/ay-a/p/7900274.html touch -t .x86_64.rpm 记得 wind ...

  9. &lbrack;Solution&rsqb; 893&period; Groups of Special-Equivalent Strings

    Difficulty: Easy Problem You are given an array A of strings. Two strings S and T are special-equiva ...

  10. DAY04、流程控制if、while、for

    一.if 判断 语法一: if 条件: # 以下是上一条if 的子代码块 print(子代码1) print(子代码2) print(子代码3) 示例: # 路边飘过一个生物,要不要表白? sex = ...