China Open source community
站内导航:
站内排行前50热点文章

精华文章  GDB调试精粹及使用实例
普通文章  STL中map用法详解
精华文章  负载均衡软件比较(Hapr...
普通文章  头文件的重复引用
普通文章  递归函数的调用过程
普通文章  TCP三次握手/四次挥手详解
普通文章  贪心策略的理论基础——...
普通文章  BMH算法原理与实现(模...
普通文章  排列组合与回溯算法
普通文章  DP动态规划
精华文章  Android线程模型
普通文章  Linux socket编程之套接字
普通文章  Linux内核中的红黑树
精华文章  linux下使用minicom的几...
普通文章  Java开源Html解析类库
精华文章  enum类型的本质
普通文章  memcached server LRU ...
普通文章  linux设置环境变量的方法
普通文章  android核心模块及相关...
普通文章  linux源代码包(.tar.g...
普通文章  L.A.M.P配置过程
普通文章  在ubuntu9.10下安装QT4...
普通文章  C/C++程序员常见面试题...
普通文章  gcc编译过程概述
普通文章  python的memcache和jso...
普通文章  应用程序二进制接口---ABI
普通文章  linux内核编译问题
普通文章  Java多线程实现简单实例
普通文章  Python程序员常用的IDE...
普通文章  brk和sbrk详述
普通文章  优化C语言代码(程序员必...
普通文章  python非贪婪,多行匹配...
普通文章  函数指针传递和全局指针...
普通文章  Unix操作系统的历史演变
普通文章  网络编程之C10K问题
普通文章  发行版发布:CentOS 5.4
普通文章  在windows中构建gtk开发...
普通文章  i++循环与i--循环的执行...
普通文章  关于Qvariant类--万能的...
普通文章  Debian sudo 设置
普通文章  busybox1.15.x 交叉编译
普通文章  关于僵死进程zombie
普通文章  递归思想的妙用
普通文章  判断链表是否存在环并找...
普通文章  Android Porting Exper...
普通文章  关于/etc/bashrc和$HOM...
普通文章  [翻译]Django初窥
普通文章  Python list的排序
普通文章  Django实现大数据量分页...
普通文章  Debug方式取代printf满...

 
 
 
当前位置: 首页 >> 程序设计 >> C/C++编程 >> 指针与数组
 
 

指针与数组

作者:ohy3686      来源:ohy3686.cublog.cn     发表时间:2006-11-30     浏览次数:      字号:    

指针与数组学习笔记
OHY 2006-11-27
   C语言中指针与数组这两个概念之间的联系是密不可分的,以至于如果不能理解一个概念,就无法彻底理解另一个概念。
   C语言中的数组值得注意的地方有以下两点:
   1、C语言中只有一维数组,而且数组的大小必须在编译期就作为一个常数确定下来。然而,C语言中数组的元素可以是任何类型的对象,当然也可以是另外一个数组。这样,要“仿真”出一个多维数组就不是一件难事。
   2、对于一个数组,我们只能够做两件事:确定该数组的大小,以及获得指向该数组下标为0的元素的指针。其他有关数组的操作,哪怕它们看上去是以数组下标进行运算的,实际上都是通过指针进行的。换句话说,任何一个数组下标运算都等同于一个对应的指针运算,因此我们完全可以依据指针行为定义数组下标的行为。
  
理解C语言中数组运作机制的注意点:
一、理解如何声明一个数组
   1、例如:int  calendar[12][31];
   声明了calendar是一个数组,该数组拥有12个数组类型的元素,其中每个元素都是一个拥有31个整型元素的数组。因此,sizeof(calendar)的值是(31×12)与sizeof(int)的乘积。
   如果calendar不是用于sizeof的操作数,而是用于其他的场合,那么calendar总是被转换成一个指向calendar数组起始元素的指针。
 
   2、任何指针都是指向某种类型的变量,如:int* ip;表明ip是一个指向整型变量的指针。如果一个指针指向的是一个数组中的一个元素,那么我们只要给这个指针加1,就能够得到指向该数组中下一个元素的指针。同样地,给这个指针减1,得到的就是指向该数组中前一个元素的指针。
   注意,给一个指针加上一个整数,与给该指针的二进制表示加上同样的整数,两者是截然不同。如果ip指向一个整数,那么ip+1指向的是计算机内存中的下一个整数,在大多数现代计算机中,它都不同于ip所指向地址的下一个内存位置。
 
   3、如果两个指针指向的是同一个数组中的元素,把两个指针相减是有意义的。例如:int* q = p + i;那么我们可以通过q - p得到i的值。需要注意的是如果q和p指向的不是同一个数组,即使它们所指向的地址在内存中的位置正好间隔一个数组元素的整数被,所得到的结果仍然是无法保证其正确性。
 
   4、如果我们在应该出现指针的地方,却采用了数组名来替换,那么数组名就被当作指向该数组下标为0的元素的指针。
例如:int* p;
      int a[3];
      p = a;  就会把数组a中下标为0的元素的地址赋值给p。如果写成p=&a;在ANSI C中是非法的,因为&a是一个指向数组的指针,而p是一个指向整型变量的指针,它们的类型不匹配。
   因此,我们可以知道,*a就是数组a中下标为0的元素的引用。例如,*a=88;就是将数组a中下标为0的元素的值设置为88。同样的道理,*(a+1)就是数组下标为1的元素的引用。以次类推,*(a+i)就是数组a中下标为i的元素的引用。这种写法是如此常用,因此它被简记为a[i]。
 
二、二维数组
二维数组实际上是一数组为元素的一维数组。
例如:int calendar[12][31];
      int *p;
      int i;
calendar是一个有12个数组类型元素的数组,它的每个数组类型元素是一个有着31个整型元素的数组,所以,calendar[4]是calendar数组的第5个元素,是calendar数组中12个有着31个整型元素的数组之一。因此,calendar[4]的行为也就表现为一个有着31个整型元素的数组的行为。
例如:sizeof(calendar[4])的结果是31与sizeof(int)的乘积。
例如:p = calendar[4];使指针p指向数组calendar[4]中下标为0的元素。
因此:i=calendar[4][7]=*(calendar[4]+7)=*(*(calendar[4])+7);
显然:用带方括号的下标形式很明显地要比完全用指针来表达要简单得多。
注意:p = calendar;是非法的。
因为calendar是一个二维数组,即“数组的数组”,在此处的上下文中使用calendar名称会将其转换为一个指向数组的指针;而p是一个指向整型变量的指针。
但是:int (*ap)[31];声明了*ap是一个拥有31个整型元素的数组,因此,ap就是一个指向这样数组的指针。因而,我们可以这样写:
int calendar[12][31];
int (*monthp)[31]; 
monthp= calendar;
这样,monthp将指向数组calendar的第一个元素,也就是数组calendar的12个有着31个元素的数组类型元素之一。
 

编辑 webmaster

 
 
 
 
中国源码网 - www.YuanMa.org - 中国 开放源代码+编程 社区