您的位置:首页 > 其它

数组与指针

2017-03-17 11:35 225 查看

数组

数组是指具有相同类型的数据组成的序列,是有序集合。(教科书上的定义)

即:数组就是内存中一段连续的存储空间。那么我们怎么使用它呢?用数组名。也就是我们用数组名可以在内存中找到对应的数组空间,即数组名对应着地址。对应着首元素的地址,所以,我们可以通过数组的首元素地址来找到数组

数组名是一个地址(首元素地址),即是一个指针常量。

只有在两种场合下,数组名并不用指针常量来表示:

1. sizeof(数组名) ; sizeof返回整个数组的长度,而不是指向数组的指针长度。

2. &数组名 ; 产生的是一个指向整个数组的指针,而不是一个指向某个指针常量的指针。

&a[0] 与 &a 的区别:

两者的值相同,但意义不同。

&a[0]是指数组首元素的地址。&a是整个数组的地址。两者的值相同。

a+1 与 &a+1 的区别:

数组名a除了在上述两种情况下,均用&a[0]来代替。

a+1即等同于&a[0]+1。

注意:指针(地址)与常数相加减,不是简单地算术运算,而是以当前指针指向的对象的存储长度为单位来计算的。

即:指向的地址+常数*(指向的对象的存储长度)

&a[0]为数组首元素的地址。

故&a[0]+1 越过一个数组元素长度的位置。即:&a[0]+1*sizeof(a[0])。

&a为整个数组的地址。(只是用首元素地址来表示,其实际代表的意义是整个数组)

故&a+1 越过整个数组长度的位置,到达数组a后面第一个位置。 即:&a+1*sizeof(a)。

指针

指针与取地址

#include<stdio.h>
#include<stdlib.h>
int main()
{
int *a = (int*)malloc(sizeof(int));
*a = 1;
printf("\na = %d", *a);
printf("\na heap address = %p", a);
printf("\n&a stack address = %p", &a);
printf("\n");
}


结果如下(程序打印出的结果不尽相同):

a = 1
a heap address = 0x7fd67bc000e0
&a stack address = 0x7fff528d8ac8


第一行表示 变量a的值为1

第二行表示 变量a所存储的内存地址0x7fd67bc000e0,(存放整数 ‘1’ 所用的4个bytes, 64位机器的话就是8个bytes),这块内存在堆上-heap

第三行表示 变量a本身(一个整数型指针 int* )的内存地址0x7fff528d8ac8,这块内存在栈上-stack。

#include<stdio.h>

int main()
{
int num = 7;
int *p = #//初始化指针,也可以写作int* p = #
printf("%d 的地址是 %p\n", num, p);
return 0;
}

//7 的地址是 0x7fff5a2d5b28


上面int p定义了一个指向int类型指针p(我们使用符号把p声明为指针),并初始化p使其指向int类型的变量num,这里&num中的&是取地址操作符,当&作用于一个对象上时,它返回了该对象的地址。

所以这里指针p指向了num所对应的地址。

解引用与指针赋值

#include<stdio.h>

int main(void)
{
int num = 7;
int *p = #
printf("数值%d所在的地址是 %p\n", num, p);
printf("指针p所指向的地址为 %p , 该地址上所保存的值为%d\n", p, *p);
*p = 100;
printf("指针p所指向的地址为 %p , 该地址上所保存的值为%d\n", p, num);
printf("num: %d\n", num);
return 0;
}


数值7所在的地址是 0x7fff5ce40b28

指针p所指向的地址为 0x7fff5ce40b28 , 该地址上所保存的值为7

指针p所指向的地址为 0x7fff5ce40b28 , 该地址上所保存的值为100

num: 100

注意这里*操作符为解引用操作符,它返回指针p所指的对象(左值)。

我们可以对*p赋值(对左值赋值),从而改变p所指的地址上所保存的值,从而改变此地址所存储的变量num的值。

#include<stdio.h>

int main(void)
{
int num = 7, another = -5;
int *p = #
p = &another;
printf("%d\n", *p);//此时p指向了another,所以输出了another的值,即-5
return 0;
}
//-5


当然,我们也可以给指针p赋值,使其指向另外一个地址,这样就改变了在解引用时获取的左值。

指针表达式

注意:*与++优先级相同,且它们的结合性都是从右向左的。

例:对于 *cp++ ; 我们可以把它分解为: *cp 之后再 cp++

对于 *++cp ; 我们可以把它分解为:++cp 之后再*cp

数组与指针

#include<stdio.h>

int main(void)
{
int val[100];
for (int i = 0; i < 100; ++i)
val[i] = i;
int *p = val;///近似理解为 int *p = &val[0];
///这里发生了隐式指针转换:数组自动转换为指向第一个元素的指针
printf("%d\n", *p); ///指针p指向val的第一个元素,即val[0]

int t = 100;
while (t--)
///可以直接对指针进行加减运算,就和迭代器一样
printf("%d\n", *(p++));///输出0~99

///指针可以做差:
int *p2 = &val[10], *p3 = &val[20];
printf("%d\n", p3 - p2); //10
printf("%d\n", p2 - p3); //-10

///还可以比比较大小:
printf("%d\n", p2 < p3 ? p3 - p2 : p2 - p3); //10
return 0;
}


注意:

两个指针直接相加是不允许的。(你要真想把两个地址值相加,把它们先都强制转换为int型即可)

两个指针直接相减在语法上是允许的。(但必须相对于同一个数组,结果是两指针指向位置相隔的元素个数)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  指针 数组