数组与指针

原创 2007年10月12日 10:27:00

有一天无意之间看到一篇文章很不错,里面总结了一些指针与数组的关系,概括性很强,文章在下面,看的时候发现有些问题,说的不是很好懂,我说说我的见解:

首先指针和数组的名字表示的就是一个首地址,这一点可以肯定,但是数组是在堆里分配,而指针是在栈里分配,两者有者本质的区别,数组是有固定的地址,但是指针如果不使用new或者malloc的话,那么他就是处在一个“游离”的状态。

先看下面的文章,我再说说一些要记住的,或者说要注意的!

什么时候数组与指针相同

所有作为函数参数的数组名总是可以通过编译器转换为指针。
在其他所有情况下,数组的声明就是数组,指针的声明就是指针,两者不能混淆。

但在语句或表达式中引用时,数组总是可以写成指针的形式,两者可以互换。

然而,数组和指针在编译器处理时是不同的,在运行时的表示形式也是不一样的。
对编译器而言,一个数组就是一个地址,一个指针就是一个地址的地址,你应该根据情况做出选择。

为什么会发生混淆

当人们学习编程时,一开始总是把所有的代码都放到一个函数里。
随着水平的进步,他们把代码分别放在几个函数中。
在水平继续提高后,他们最终学会了如何用几个文件来构造一个程序。

什么时候数组和指针是相同的?C语言标准对此作了如下说明:
规则1 表达式中的数组名(与声明不同)被编译器当作一个指向该数组第一个元素的指针。
规则2 下标总是与指针的偏移量相同。
规则3 在函数参数的声明中,数组名被编译器当作指向该数组的第一个元素的指针。

规则1:“表达式中的数组名”就是指针

规则1和2合在一起理解,就是对数组下标的引用总是可以写成“一个指向数组的起始地址的指针加上偏移量。”
(个人认为,表述为“一个指向该数组第一个元素的指针加上偏移量”更明确。)

对数组的引用如a[i]在编译时总是被编译器改写成*(a+i)的形式。
C语言标准要求编译器必须具备这个概念性的行为。
于是,a[6]和6[a]都是正确的。

编译器自动把下标值的步长调整到数组元素的大小。
这就是为什么指针总是有类型限制,每个指针只能指向一种类型的原因,
因为编译器需要知道对指针进行解除引用操作时应取几个字节,以及每个下标的步长应取几个字节。

规则2:C语言把数组下标作为指针的偏移量

事实上,下标范围检测被认为并不值得加入到C语言中。

数组下标是定义在指针的基础上的,所以优化器常常可以把它转换为更有效率的指针表达式,
并生成相同的机器指令。

C语言把数组下标改写成指针偏移量的根本原因是指针和偏移量是底层硬件所使用的基本模型。

为什么C语言把数组形参当作指针

之所以要把传递给函数的数组参数转换为指针是出于效率的考虑,
这个理由常常也是对违反软件工程做法的辩解。

我们倾向于始终把参数定义为指针,因为这是编译器内部所使用的形式。
但从另一方面,有些人觉得int table[]比int *table更能表达程序员的意图。

数组片段的下标

向函数传递数组前面一个位置的地址(a[-1]),这样就可以使数组下标从1到N,而不是从0到N-1。
不幸的是,这个手段完全为标准所不容,所以你千万不要告诉别人是我告诉了你这个方法。

C语言的多维数组

但所有其他语言都把这称为“数组的数组”

C语言里有一种别的语言称为数组的数组的形式,但C语言称它为多维数组。
C语言中的数组就是一维数组,而这个数组的元素可以是另一个数组。

编译器在编译时会把carrot[i][j]解析为*(*(carrot+i)+j)的形式。

如何分解多维数组

在“数组的数组的数组”中的每一个单独的数组都可以看作是一个指针。
这是因为在表达式中的数组名被编译器当作“指向数组第一个元素的指针”。

内存中数组是如何布局的

在C语言的多维数组中,最右边的下标是最先变化的,这个约定称为“行主序”。

如何对数组进行初始化

只能够在数组声明时对它进行整体的初始化。
之所以存在这个限制,并没有过硬的理由。

在IEEE754标准浮点数实现中,0.0和0的位模式是完全一样的。

初始化二维字符串数组:
char vegetables[][9] =
{
"beet",
"barley",
"basil",
"broccoli",
"beanes"
};

一种有用的方法是建立指针数组,字符串常量可以数组初始化值:
char *vegetables[] =
{
"beet",
"barley",
"basil",
"broccoli",
"beanes"
}; 

以上是人家的文章的内容,看完之后肯定感觉很不错吧,在上面的内容之余我再补充点东西:

对于:

char heart[] = "asdfasdf";

char *head = "gggggggggg";

由上面的文章我们可以知道,使用数组的方法和指针的方法都可以,即:可以用heart[i],head[i],又可以使用*(heart+i),*(head+i),但是是不是都可以自加或者自减 哦?

不是

指针可以,开始我们说了指针可以认为是游离的,所以他本身的值可以变化,而自加就是让指针的首地址变化,但是数组是固定的,要变化一个数组的首地址就要用到双指针,如**heart,这里不说,试图用单指针变化数组的首地址是不行的。

另外,可以把一个数组赋值给指针,但是不可以把一个指针赋值给数组,也是这个道理!这也就是为什么指针申明和定义分开进行可以,如:

char *p;

p = "asdf";

但是指针不可以如

char p[5];

p = "asdf";//试图改变数组的首地址!wrong!

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ztz0223/article/details/1821332

指针与数组的对比---------------------------------------

  • 2008年12月19日 09:14
  • 34KB
  • 下载

指针与数组.txt 指针与数组.txt

  • 2008年11月17日 10:25
  • 9KB
  • 下载

<指针与数组定义小结>

  • 2009年09月04日 10:28
  • 26KB
  • 下载

数组的指针和指向数组的指针变量

  • 2010年03月20日 18:15
  • 65KB
  • 下载

数组与指针间的转换浅析

可以允许把指针好像数组名一样进行标记 #define N 100 int a[N],i,sum=0,*p=a; for(i=0;i sum+=p[i]; 对待p[i]就像对待*(p+i)一样...
  • Moon_K_H
  • Moon_K_H
  • 2015-01-09 22:35:30
  • 2476

C++数组与指针深入剖析

  • 2010年09月10日 10:36
  • 278KB
  • 下载

【C++】有关c++中数组与指针的关系

下图是代码与运行结果: 1.简单数组与指针的关系(int型数组为例): 解释: 第二句相当于int型指针cp指向了数组的第一个元素,所以,打印出的cp是第一个元素的地址;&cp[0]与...
  • wendongxia
  • wendongxia
  • 2017-02-26 15:39:56
  • 1260

数组与指针的艺术.doc

  • 2010年12月28日 10:56
  • 192KB
  • 下载

数组指针和保存指针的数组

1、数组指针:指向多维数组。 如:int ia[3][4];        int (*ip)[4] = ia;  //ip points to an array of 4 ints      ...
  • mdtkzc
  • mdtkzc
  • 2014-12-09 19:38:37
  • 277

用指针表示数组

用指针表示二维数组:int a[3][2] = {1, 2, 3, 4, 5, 6};                                     int i, j;         ...
  • wzx104104104
  • wzx104104104
  • 2017-05-08 17:19:46
  • 758
收藏助手
不良信息举报
您举报文章:数组与指针
举报原因:
原因补充:

(最多只允许输入30个字)