指针剖析,地址关系 (二) 数组与指针、数组名的关系

 

一:先看代码  vim 13.c

 

 

 

#include <iostream>

#include <cstring>

#ifndef   NUM

#define   NUM  10

 

#endif

using namespace std;

 

int main()

{

int i=0;

int *p = &i ;

 

int a[NUM]={1,2,3,4,5,6};

 

// int *q = a;

 //int *q = &a; 这样赋值不可以

   int *q = &a[0];

cout<<"先输出a[0] a[1] 的地址和内容"<<endl;

cout<<"a[0]地址   "<<&a[0]<<"   a[0]内容   "<<a[0]<<endl;

cout<<"a[1]地址   "<<&a[1]<<"   a[1]内容   "<<a[1]<<endl;

 

cout<<"先看看顺序存储的内存分配情况:"<<endl;

for(int n=0;n<NUM;n++)

{

cout<<&*(q++)<<"    对应内容   "<<*q<<endl;

}

cout<<"以上数组输出结束!下面看看a,&a,p,&p的输出。"<<endl;

cout<<"i = "<<i<<endl;

cout<<"p = "<<p<<endl;

cout<<"&p= "<<&p<<endl;

cout<<"*p= "<<*p<<endl;

 

cout<<"&a= "<<&a<<endl;

cout<<"a = "<<a<<endl;

cout<<"&a[0]= "<<&a[0]<<endl;

cout<<"a[0]="<<a[0]<<endl;

cout<<"q = "<<q<<endl;

cout<<"&q= "<<&q<<endl;

cout<<"发现没有,a 和 &a 一样。"<<endl   ;

return 0;

}

 

  
二:编译代码  g++ 13.c -o 13
       
三:查看输出   cyq@cyq-desktop:~/桌面/C$ ./13

 

 

先输出a[0] a[1] 的地址和内容
a[0]地址   0xbf901624   a[0]内容   1
a[1]地址   0xbf901628   a[1]内容   2
先看看顺序存储的内存分配情况:
0xbf901624    对应内容   1
0xbf901628    对应内容   2
0xbf90162c    对应内容   3
0xbf901630    对应内容   4
0xbf901634    对应内容   5
0xbf901638    对应内容   6
0xbf90163c    对应内容   0
0xbf901640    对应内容   0
0xbf901644    对应内容   0
0xbf901648    对应内容   0
以上数组输出结束!下面看看a,&a,p,&p的输出。
i = 0
p = 0xbf901658
&p= 0xbf901654
*p= 0
&a= 0xbf901624
a = 0xbf901624
&a[0]= 0xbf901624
a[0]=1
q = 0xbf90164c
&q= 0xbf901650
发现没有,a 和 &a 一样。
    
四:总结分析
       
1. 由于,数组连续分配内存,所以可以看到数组中的变量的内存是连续的,因为是int 型,所以地址相差4字节
(进一步说,内存大小按字节分配,字节是最小单位)
数组  a[NUM]中,a的值就是a[0]的地址,而&a与a是一样的。但是,a[0]的内容和a不一样
  
尽管如此 (&a与a的值是一样的),但是还是不能这样赋值
  
int *q =  &a  ;//这是错误的  可能因为a的内容不是int 型吧。用g++会报这样的错:
13.c:17: 错误: 不能将‘int (*)[10]’转换为‘int*’,在 initialization 中
   
当然可以这样赋值
   
int *q = &a[0] ;
2.再分析一下,&a和a到底是什么

 

数组 a,
他仅仅是个标签,根本就没地方存放。

 

事实上,编译器没有给a分配内存。

 

所以C语言中的规定是取数组地址的结果是:仍然是其本身。
既 &a 的值和 a一样。
注意:值是一样,类型是不一样的。

------------------------

虽然数组名的确没有存储空间,但把&a规定为跟a的地址值一样并不是这个原因。
数组名是一个右值,本来不符合&的语法的,但是,数组却是一个对象,对一个
数组对象取地址是合理的,C标准委员会经过衡量,认为维护一个对象的完整性
更重要,因此允许&a,只不过,&a的意义,并非对一个数组名取地址,而是对
一个数组对象取地址。

              
     
   
3.再看看这个问题 代码中的  cout<<&*(q++)<<"    对应内容   "<<*q<<endl;   这行。
           
   很多人不理解 q++是什么意思,实际上q++是指,q的内容加一,也就是说q再增加一个q单位。
   那么一个q单位是多少,因为我们定义为  int *q = &a[0]  ,那么显然,一个q单位大小因该
   为4个字节(因为一个int 变量占用4个字节嘛 )
   所以如果     q=0xbfe70058    那么  当执行完q++之后  ,q=0xbfe7005c   ,前后差4   。
    如果不信,可以在代码中加入这行看看
cout<<"sizeof(q)=" <<sizeof(q)<<endl;
cout<<"++q="<<++q<<endl; 
当然如果你感兴趣,可以再加一行这个,看看&q
cout<<"sizeof(&q)= "<<sizeof(&q)<<endl;
cout<<"++(&q)= "<<&q+1<<endl;
// cout<<"++(&q)="<<++(&p)<<endl;  这行如果这么写是错误的,用上面一行代替即可。 
      
最后我们再思考一下:
由于数组分配连续内存,那么我们能进一步想到什么呢?
    如果在程序中多用数组的话,内存的使用效率会很低(低于用指针链表),如果内存中,有的内存断大小不够一整块内存来分配给数组用,那么这块内存就被浪费掉了。所以这就是数组的一大缺点。当然还有很多,比如增删改查的问题等等。
参考:
 

 

声明:本文档可以随意更改,但必须署名原作者

作者:凤凰舞者 qq:578989855

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值