数组与指针

原创 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!

版权声明:本文为博主原创文章,未经博主允许不得转载。

指针数组与数组指针详解

指针数组与数组指针详解1.什么是指针数组和数组指针? 指针数组:指针数组可以说成是”指针的数组”,首先这个变量是一个数组,其次,”指针”修饰这个数组,意思是说这个数组的所有元素都是指针类型,在32位系...
  • men_wen
  • men_wen
  • 2016年09月28日 21:21
  • 9686

指针数组,数组指针与二维数组剖析

int *p[3]与int (*p)[3]的区别 *p[3]这个是一个指针数组,它所代表的意思是数组中的每一个元素都是一个指针变量,而(*p)[3],p是一个指针变量,表示指向一个含有3个整型元素的一...
  • qiumingjian
  • qiumingjian
  • 2015年05月06日 17:24
  • 3335

数组指针和指针数组的区别

数组指针和指针数组的区别中国的文字博大精深,不仔细研读,很容易理解错误,就拿这个数组指针和指针数组来说吧,刚开始接触很容易弄混 那么到底什么是数组指针?什么是指针数组?他们之间又有什么区别?* 指...
  • qq_30137611
  • qq_30137611
  • 2016年10月01日 00:25
  • 559

用指针给数组赋值的一个小问题

问题是这样的, 我打算输入与元素为数组赋值, 然后反向输出数组元素# include int main(void) { int a[10], * p = a, i; for (i...
  • williamgavin
  • williamgavin
  • 2017年06月03日 11:28
  • 2211

面试题之数组指针和指针数组的区别

1、数组指针(指向数组的指针) (1)数组在内存中的表示 创建一个数组就是在内存里面开辟一块连续的空间,比如int a[4];就是在内存里面开辟了一个大小为4*sizeof(int)字节的...
  • sum_TW
  • sum_TW
  • 2016年12月09日 16:28
  • 3903

指针数组和数组指针的区别

变量类型判断:变量和哪个关键字先结合,该变量就是什么类型。  例如 (1)int (*p)[n];   //p先和*结合,故是一个数组指针 ,即指针指向一个数组 (2) int *p...
  • kulala082
  • kulala082
  • 2016年11月30日 14:35
  • 1094

指针数组数组传参、指针引用传参

指针和数组作为参数传入函数时,传入的是地址,即指向变量的地址和数组的首地址,可以在函数中改变指针或数组的值,但本质上它们还是值的传递(区别于变量的值传递的是:变量值传递不会改变实参原来的值。),我们无...
  • dongchongyang
  • dongchongyang
  • 2016年09月17日 23:47
  • 1491

c/c++(疑4) 指针数组和数组指针之间关系

指针数组和数组指针概述(数组指针(指向数组的指针)与指针数组(存放指针的数组)) 指针数组:首先它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身决定。它是“储存指针的数组”的简称。 数...
  • u010236550
  • u010236550
  • 2015年05月08日 11:49
  • 2023

函数指针和函数指针数组及其应用

1. 函数指针 先来看一个简单的例子。 int a=3; void *p=&a; 这是一个基础的不能再基础的例子。相信学过指针的都能看得懂。P是一个指针,指向a。a 是一个整形变量。 函数指针和其类似...
  • yuexiang321
  • yuexiang321
  • 2016年09月25日 11:07
  • 1866

如何正确使用指针数组?(警醒)

如何正确使用指针数组? 程序代码: #include  void man(int*a[]); void exchange(int*x,int*y); int main()//求输入10个...
  • wbb1997
  • wbb1997
  • 2017年04月15日 13:38
  • 176
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:数组与指针
举报原因:
原因补充:

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