为生存而奔跑

   :: 首页 :: 联系 :: 聚合  :: 管理
  271 Posts :: 0 Stories :: 58 Comments :: 0 Trackbacks

留言簿(5)

我参与的团队

搜索

  •  

积分与排名

  • 积分 - 324044
  • 排名 - 74

最新评论

阅读排行榜

评论排行榜

在其它高级语言里,不管是定义(声明)还是引用,a[i]a[3]都是一个整体。在C/C++里,却是一个表达式:a[i]是运算符[]连接两个实体ai

C/C++并没有数组,有以下几条理由。

理由一:C里没有数组形式。

“数组”名a本身就是一个指针,与常规指针不同的是,它是一个不能移动的所谓常指针。

如在函数外有定义:

float a[3] = {1.0, 2.0, 3.0};

首先在初始化数据段分配一块能容纳三个float数的空间,并填入三个初始值,然后定义一个名为a指向float数据流的常指针,并使其指向该区域的首字节。

理由二:“数组”的定义,其实最终是对指针的定义。

说“指向float数据流”,和说“指向float型数组”,是两个概念。共性是,计算偏移量(我不说移动,因为常指针是不能移动的。)时,计算单位都是float型数据的字节数。但是,数组是有边界的,你的下标不能超出边界。而偏移量可以超出数据流的边界(后果自负)。

很多书里说,C“数组”没有边界检查,是为了运行效率。但是,对边界的检查,系统开销并不大。C里的“数组”其实是个数据流,它的边界只有一头:常指针所指向的下边界。

理由三:数组名和下标竟然可以互换。

我们要访问上面那个数据流的第2个数据,可以使用a[1],也可以使用*(a + 1)。两者完全等价。我怀疑,C的作者所提供的a[i],仅仅是*(a + i)的同义词。按照加法交换率,显然,*(a + i)等于*(i + a)。那i[a]是不是也等于a[i]呢?测试结果:等于。更奇怪的是,不但i[a]等于a[i]1[a]也等于a[1]

看看下面的相等关系:

      a[1] 等于 *(a + 1) 等于 *(1 + a) 等于 1[a]

上面的怀疑或许有点道理了。

理由四:a[i]无非是*(a + i)的同义词。

对“数组”的访问,最终总是通过指针的。其基本形式是:*(a + i)

“数组”名是一个常指针,总是指向该区域的首址。“下标”其实是一个逻辑偏移量。说它是“逻辑”的,意思是在计算时,需要乘以步长(数据的长度)。但是,这个“乘法”对你是透明的,不必关心它。指向所访问数据的是常指针“加”偏移量。

X86系列CPU的指令系统里,有一个基址变址寻址方式。这种寻址方式和C对“数组”的访问方式很相似。常指针相当于基址,偏移量相当于变址。

我怀疑,这个基址变址寻址方式是为C访问“数组”而增加的。

理由五:C“数组”没有上边界。

对下面的定义

float a[3] = {1.0, 2.0, 3.0};

我们不仅可以访问a[0]a[1]a[2],还可以访问a[3]a[4]等。C数组不知道自己的一亩三分到哪里为止。用C/C++开发,与用其它语言不同,编程员必须记住自己定义的数组有多大。自己的家没有栅栏,跑到邻居割韭菜没人管,但后果自负。

理由六:对“多维数组”的访问总是可化解成对“一维数组”的方式。

诚然,不管是用哪种语言编程,最终生成的目的码中,数组总是被转换成一块连续的存储区(即它是线状的)。不同的是,在C源码里,所有的数组,不管是几维的,都是线状的。在源码层面,都可以看作是一维的。定义了

      int  a[3][4];

可以用a[2][3],也可以用a[11]访问其第2行、第3列元素。

结论

C里使用下标运算符[],无非是使指向一串等类型元素的指针对该区域的操作看起来像操作数组而已。没有这东西,习惯了其它高级语言数组操作的编码员会觉得不习惯。

posted on 2011-01-01 19:12 baby-fly 阅读(1026) 评论(12)  编辑 收藏 引用 所属分类: 无聊

Feedback

# re: C/C++没有数组 2011-01-17 12:45 asda
不错  回复  更多评论
  

# re: C/C++没有数组 2011-01-17 21:14 sdas
a[11] 你是做不到的...b[11]或许可以  回复  更多评论
  

# re: C/C++没有数组 2011-01-17 21:18 sdas
(*a)[11]  回复  更多评论
  

# re: C/C++没有数组 2011-01-19 11:39 asda
a[0][11]
0[a][11]  回复  更多评论
  

# re: C/C++没有数组 2011-01-19 11:49 asda
a[5][4][6][3][7]

==

5[a][4][6][3][7]

其他组合就不行,第一阶的运算 *(a+5)=*(5+a)  回复  更多评论
  

# re: C/C++没有数组 2011-01-19 13:10 asda
声明1个 ***a 代表的是3阶等级的指针
只要运算式中不出现3阶消去指针特性的运算,就不会给出地址所指向的值.

比如 **a ,虽然((a+0)+0)地址上是有值的,但是由于表达式开始发觉一个3阶的指针对象参与了运算,所以必须出现3个* 号才能将地址的值输出,否则都是3阶地址属性封装该指针..  回复  更多评论
  

# re: C/C++没有数组 2011-01-19 13:16 asda
但是..指针对象 a 是有地址的,也有内容,内容自然就是指向的对象的地址  回复  更多评论
  

# re: C/C++没有数组 2011-01-19 13:18 asda
数组名那个指针,就只是指着自己 自己的地址 的内容 是自己的地址  回复  更多评论
  

# re: C/C++没有数组 2011-01-19 13:21 asda
所有的指针都是结构对象 有自己的参数表..
自己的值
编译时是 指向值的类名

运行时是 指向值的长度  回复  更多评论
  

# re: C/C++没有数组 2011-01-19 23:28 asda
数组名是常量,在编译后直接变成程序的栈段数组块"地址值"所以不是一个指针对象

而仅仅是个地址值..

*可以操作地址值

所以之前的推论有部分就得重新思考
  回复  更多评论
  

# re: C/C++没有数组 2011-01-20 10:38 asda
后来又考虑了很多.....也是推论了这次

数组名是否会分配空间,取决于你程序中是否需要..或许可以在同一段程序里既出现为数组名分配空间也出现不为数组名分配空间的做法..

分配空间就是,数组名被引用
不分配空间就是,数组名直接编译为常量  回复  更多评论
  

# re: C/C++没有数组 2011-01-20 10:41 asda
数组名的指针运算可能就会使数组被引用..

这看来取决于编译器是如何看待 指针运算的对象的..  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理