c语言数组和指针都有地址么,闷骚程序猿的干货之一:C语言中数组、指针和地址的异同...

声明:本文只是楼主的一家之言,只具有一点点的参考价值。如果你发现有什么不对的地方,欢迎指出,或者你可以当楼主在放一种气体。

本文将采用举例子的修辞手法,来通俗易懂的讲解指针、数组和地址之间的关系。

一、基本概念

数组:是一种数据结构,是一组相同数据元素的集合。

指针:带有类型的一个地址。

地址:芯片要存储数据,数据总要有个存储地址吧。

二、数组

首先定义一个数组int array[10];众所周知,这是一个int类型的数组,该数组有10个元素,每个元素都是一个int类型的变量。array是这个数组的数组名,但同时array也是该数组首元素的地址,所以有以下等式成立array=&array[0]。既然array是数组首元素的地址,那么一但数组定义好后,array就是一个定值。所以也就不存在array=array+1;或array++;的情况。

再看例子,int num; num=&(array[5]) - &(array[4]); 此时num=1。

原因分析:从数值上来看,array[5]的地址和array[4]的地址之间应该相差了4个字节,因为array数组是一个int类型的数组,每个元素应当占据4个字节的空间。此处就体现出来数组元素地址(其实就是指针)与真正的内存地址之间的差别。数组元素地址是有类型的,而内存地址是没有类型的。有了类型之后,两者相减,就不是数值上相减,而是计算了两者的偏移量。因为他们是int类型的,每个int类型占据4个字节,所以相当于是偏移量1个单位。

同理,um=(char*)(&(array[5])) - (char*)(&(array[4])); 此时num=4。 理由同上,不赘述。

另外sizeof(array) = 40。sizeof是在计算array数组所占据的空间,10×4=40个字节。

三、指针

带有类型的一个地址。指针的类型有其指向变量的类型决定。但void*类型的指针,是无类型的,也可以理解为它可以指向任何类型。

看例子,int *p;

int array[10];

p=array;

则以下等式成立,p = &(array[0]) = &(p[0]); *p = array[0] =p[0];

解析:根据前面介绍的,array是数组首元素的地址,那么p=array以后,p也就指向了array数组的首元素。p是一 个指针,为什么可以有p[0]这种表达形式,请自行查阅下标运算符[]的用法。

以下等式也成立,p+1 = &array[1]; 因为p是有类型的,所以p加1,是加p所指向的类型的长度,在此处是 int,所以在数值上是加4,而不是加1。

同时p也是一个变量,只不过它是一个指针变量。所以可以给p赋各种值,如p=&(array[5]);那么此时p+1就 等于&(array[6])。

关于sizeof的计算。sizeof(array)=40; 因为array数组占据40个自己;而sizeof(p)=4;因为p代表的仅仅是一个 地址,在32位机上,一个地址占4个字节。

再看例子:

char array[10];

char *p;

p=array;

则以下等式成立:原因如上。

(p+1) = &array[1]

(int*p)+1 = &array[4];

sizeof(array)=10;

sizeof(p)=4;

补充说明:当一个数组被当作参数传入函数时,其实传入的只是数组首元素的地址,并没有把整个数组都传入。

int func(int array[10])

{//因为并没有把整个数组传递进来,只是传了数组的首元素地址进来

//所以以下等式成立

sizeof(array) = 4;

}

四、地址

芯片内部要存储数据,数据总要有个存储地址吧,这里所指的地址,就是这个地址啊。所以存储在芯片上的任何数据都有一个地址。那么如果我们知道某些变量存储的空间,是否能不通过变量名,而是直接通过地址就能访问到它呢。理论上是可行的。

如果想把地址0X0000500地址中的内容读取出来,其实只要

char *p;

p=0X0000500; 此时p已经定位到地址0X0000500,你就可以为所欲为了。

但实际上,一般的编译器都是不允许直接给一个指针赋具体值的。只能通过间接的方式。

比如char array[10]; char *p = array; So sad!

既然芯片上所有的数据都有地址,所以一个函数也是有地址的。

根据前面所说的,把一个数组传入函数,只是把数组的首地址传进去,实际上传入了一个32位的地址而已。

同理,也可以把一个函数的地址当作参数传入进去,无非也就是传入一个32位的地址而已。

例子:

int fun_add(int x,int y)

{

return x+y;

}

int precess(int x,int y,int (*fun)())

{

return ((*fun)(x,y));

}

int main(void)

{

process(5,6,fun_add);

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值