数组与指针(C语言)

一.数组名和对数组名取地址

数组名相当于指针(指针相当于地址),即数组名指向首元素地址。
而函数名相当于函数指针,指向函数的入口地址。

当然数组名不完全等于指针。当对数组名取地址时,很多人会说给指针取地址,就是指针的指针,即二级指针嘛!当然这样的结论是错误的:()

#include<stdio.h>   
int main()   
{   
    int a[10];   
  
    printf("a:/t%p/n", a);            0012FF20         
    printf("&a:/t%p/n", &a);          0012FF20  
    printf("a+1:/t%p/n", a+1);        0012FF24 
    printf("&a+1:/t%p/n", &a+1);      0012FF48
  
    return 0;   
}

a和a+1是一个元素的内存大小(增加4),而&a+1增加的是整个数组的内存大小(增加40)。即a指向数组元素首地址,但&a为整个数组的首地址(即用元素首地址代表整个数组)!

总结:a+1表示首地址+sizeof(元素类型)。&a+1大小为:整个数组地址+sizeof(a)。

所以:数组名仅仅是“相当”于指针,而并非真的是指针,数组名是只是个常量(一个值为数组首元素址的常量),所以不能进行++或者--运算。而常量更是无法取地址的,而之所以有&a,其实这里的a的意义早已经不是当初那个数组名了,它此时代表了整个数组。

1.数组名取地址在数组指针中的体现

了解指针数组和数组指针二者之间的区别之后,继续来看下面的示例代码:


int arr[5]={1,2,3,4,5};
int (*p1)[5] = &arr;       //正确
/*下面是错误的*/
int (*p2)[5] = arr;        //编译出错

&arr 是指整个数组的首地址,而 arr 是指数组首元素的首地址,虽然二者之间的值相同,但第四行编译错误。

原因很简单,在 C 语言中,赋值符号“=”号两边的数据类型必须是相同的,如果不同,则需要显示或隐式类型转换。在这里,p1 和 p2 都是数组指针,指向的是整个数组。p1 这个定义的“=”号两边的数据类型完全一致,而 p2 这个定义的“=”号两边的数据类型就不一致了(左边的类型是指向整个数组的指针,而右边的数据类型是指向单个字符的指针),因此会提示错误信息。

二.指针数组与数组指针

*p[n]:为数组,数组里存放的元素为指针类型,即指针数组。

(*p)[n]:为指针,指针指向一个长度为n的一维数组,即数组指针;

首先,对于语句“int *p1[5]”,因为“[]”的优先级要比“*”要高,所以 p1 先与“[]”结合,构成一个数组的定义,数组名为 p1,而“int*”修饰的是数组的内容,即数组的每个元素。也就是说,该数组包含 5 个指向 int 类型数据的指针,如图 1 所示,因此,它是一个指针数组。

  图1 

其次,对于语句“int(*p2)[5]”,“()”的优先级比“[]”高,“*”号和 p2 构成一个指针的定义,指针变量名为 p2,而 int 修饰的是数组的内容,即数组的每个元素。也就是说,p2 是一个指针,它指向一个包含 5 个 int 类型数据的数组,如图 2 所示。很显然,它是一个数组指针,数组在这里并没有名字,是个匿名数组。

由此可见,对指针数组来说,首先它是一个数组,数组的元素都是指针,也就是说该数组存储的是指针,数组占多少个字节由数组本身决定;而对数组指针来说,首先它是一个指针,它指向一个数组,也就是说它是指向数组的指针,在 32 位系统下永远占 4 字节,至于它指向的数组占多少字节,这个不能够确定,要看具体情况

  指针数组 *p[n] 

指针数组:是数组——装着指针的数组。

#include "stdafx.h"
 
 
int main()
{
	int a = 1;
	int b = 2;
	int *p[2];
	p[0] = &a;
	p[1] = &b;
 
	printf("%p\n", p[0]); //a的地址
	printf("%p\n", &a); //a的地址
	printf("%p\n", p[1]); //b的地址
	printf("%p\n", &b); //b的地址
	printf("%d\n", *p[0]); //p[0]表示a的地址,则*p[0]表示a的值
	printf("%d\n", *p[1]); //p[1]表示b的地址,则*p[1]表示b的值
 
 
	//将二维数组赋给指针数组
	int *pp[3]; //一个一维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2],所以要分别赋值
	int c[3][4];
	for (int i = 0; i<3; i++)
		pp[i] = c[i];
 
	int k;
	scanf_s("%d", &k);
 
    return 0;
}
 

数组指针 (*p)[n]

数组指针:是指针——指针指向数组。

#include "stdafx.h"
 
 
int main()
{
	//一维数组
	int a[5] = { 1, 2, 3, 4, 5 };
	//步长为5的数组指针,即数组里有5个元素
	int (*p)[5];
	//把数组a的地址赋给p,则p为数组a的地址,则*p表示数组a本身
	p = &a;
 
	//%p输出地址, %d输出十进制
	//\n回车
	//在C中,在几乎所有使用数组的表达式中,数组名的值是个指针常量,也就是数组第一个元素的地址,它的类型取决于数组元素的类型。
	printf("%p\n", a); //输出数组名,一般用数组的首元素地址来标识一个数组,则输出数组首元素地址
	printf("%p\n", p); //根据上面,p为数组a的地址,输出数组a的地址
	printf("%p\n", *p); //*p表示数组a本身,一般用数组的首元素地址来标识一个数组
	printf("%p\n", &a[0]); //a[0]的地址
	printf("%p\n", &a[1]); //a[1]的地址
	printf("%p\n", p[0]); //数组首元素的地址
	printf("%d\n", **p); //*p为数组a本身,即为数组a首元素地址,则*(*p)为值,当*p为数组首元素地址时,**p表示首元素的值1
	printf("%d\n", *p[0]); //根据优先级,p[0] 表示首元素地址,则*p[0]表示首元素本身,即首元素的值1
	printf("%d\n", *p[1]); //为一个绝对值很大的负数,不表示a[1]...表示什么我还不知道
 
	
 
	//将二维数组赋给指针
	int b[3][4];
	int(*pp)[4]; //定义一个数组指针,指向含4个元素的一维数组
	pp = b; //将该二维数组的首地址赋给pp,也就是b[0]或&b[0],二维数组中pp=b和pp=&b[0]是等价的
	pp++; //pp=pp+1,该语句执行过后pp的指向从行b[0][]变为了行b[1][],pp=&b[1]
 
	int k;
	scanf_s("%d", &k);
 
    return 0;
}

根据上面二维数组可以得出,数组指针也称指向一维数组的指针,所以数组指针也称行指针。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值