对于数组名和对数组名取地址

原创 2010年08月24日 21:34:00

对于数组名和对数组名取地址

前些日子看了一个帖子,其中有个例子如下:

 int a[5]={1,2,3,4,5};
 int *p1=(int*)(&a+1);
 int *p2=(int*)((int)a+1);
 int *p3=(int*)(&a)+1;
    // p3=p3+1;
 printf("%x,%x,%x",p1[-1],*p2,p3[-1]);

执行结果为5,2000000,1。对于结果5还是比较纠结。看了一下网上的帖子和几本书,总结了一下。

 

首先说一下关于对数组名取地址:
        关于对数组名取地址的问题,由于数组名是右值,本来&array 是不合法的,早期不少编译器就是指定&array 是非法的,但后来C89/C99认为数组符合对象的语义,对一个对象取地址是合理的,因此,从维护对象的完整性出发,也允许&array 。只不过,&array 的意义并非对一个数组名取地址,而是对一个数组对象取地址,也正因为如此,array 才跟&array 所代表的地址值一样,同时sizeof(array )应该跟sizeof(&array )一样,因为sizeof(&array )代表取一个数组对象的长度。

         要注意到 array 和 &array 的类型是不同的。array为一个指针,而&array是指向数组int [100]的指针。array 相当于 &array[0],而 &array 是一个指向 int[100] 的指针,类型是 int(*)[100]。


另外从步长的角度分析这个问题
执行如下语句:
printf("array=%p, array+1=%p/n", array, array+1);
printf("&array=%p, &array+1=%p/n", &array, &array+1);

结果为:
array=0012FDF0, array+1=0012FDF4     //+sizeof(int)
&array=0012FDF0, &array+1=0012FF80  //+sizeof(&array)

在《C专家编程》书中关于数组一章P203,有如下解释:
    无论指针还是数组,在连续的内存地址上移动时,编译器都必须计算每次前进的步长。
    编译器自动把下标值调整到数组元素大小,对起始地址进行加法操作之前,编译器都会负责计算每次增加的步长,这就是为什么指针类型总是有类型限制,每个指针只能指向一种类型的原因所在,因为编译器需要知道对指针进行解除引用操作时应该取几个字节,以及每个小标的步长应取几个字节。
    另外步长的自动调整还和上下语句相关:
 int *p3=(int*)(&a);
      p3=p3+1;
    首先对P3指针变量赋初值,指向数组int [5]的指针,然后对指针进行加一的操作,其中P3定义为一个指向int类型的指针,因此最终P3的值等价P3+sizeof(int)
 int *p3=(int*)(&array+1);
    &array+1,步长为1,其中步长的长度和&array的类型匹配,即&array是指向数组int [100]的指针,所以&array+1等价为&array+sizeof(&array)
 
  最终p1[-1]等价为*(P1-1),因此等价为第二个int [5]的数据首地址(并不存在第二个数组显然当前指针已经越界了,另外数组元素在内存中是连续存贮的)减去一个为sizeof(int)的步长,所以指向了第一个数组的最后1个元素。

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

指针 数组 数组名和数组名取地址的区别

首先指针数组 和数组指针叫法本身是种误导 指针数组:array of pointers,即用于存储指针的数组,也就是数组元素都是指针 数组指针:a pointer to an array,即...
  • lx627776548
  • lx627776548
  • 2016年09月01日 15:55
  • 1331

C语言的数组名和对数组名取地址

int a[5] = {1,2,3,4,5};     int *p = (int *)(&a+1);     int *s = p-1;     int *r = a+4;     prin...
  • syzobelix
  • syzobelix
  • 2014年10月13日 22:11
  • 4545

C语言的数组名和对数组名取地址

本文摘自:http://blog.csdn.net/zdcsky123/article/details/6517811 相信不少的C语言初学者都知道,数组名相当于指针,指向数组的首地址,而函数名...
  • bird67
  • bird67
  • 2014年04月29日 14:05
  • 1422

C语言数组名取地址

面试中遇到的C语言数组名取地址的问题
  • xiaolewennofollow
  • xiaolewennofollow
  • 2016年10月02日 16:17
  • 410

二维数组名再取地址是什么

ww6582163 | 分类:互联网 | 浏览246次 分享到: 举报| 2013-11-26 18:21提问者采纳 此处...
  • Sayesan
  • Sayesan
  • 2014年09月02日 09:22
  • 1425

数组名取地址带来的问题

我们都知道数组名取地址的值和数组的首地址是同一个值,但是他们的指类是不同的,如果强转的话是会出问题的。看看下面这个程序片段: #include int foo(char **t) { printf...
  • choumin
  • choumin
  • 2016年05月08日 18:56
  • 191

数组名取地址是什么?

int a[5]={1,2,3,4,5}; int b[100]; 一个数组名代表的是数组中第一个元素的位置,通过数组名我们可以访问数组,先看下面两个问题 问题一: 看到一篇文章这...
  • fengchenlongxia
  • fengchenlongxia
  • 2013年08月28日 17:27
  • 415

验证C语言的数组名非数组首地址的代码

  • 2015年03月29日 22:30
  • 2KB
  • 下载

C语言——数组名、取数组首地址的区别(二)

目录 数组指针与指针数组 再谈array与&array的区别 array与&array的区别之讨论 array与&array的区别之总结 参考 1. 数组指针与指针数组 在初学C语言时,很难分清楚数...
  • jingzi123456789
  • jingzi123456789
  • 2017年03月29日 12:31
  • 132

数组名、取数组首地址的区别

1 int a[10]; 2 int *p = a; 3 int (*q)[10] = &a; 第二个为指向数组的指针. a只是a[0]的地址,a+1就是a[1]的地址了,&a是整个a[1...
  • weiqubo
  • weiqubo
  • 2016年10月07日 21:53
  • 2303
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:对于数组名和对数组名取地址
举报原因:
原因补充:

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