数组指针和指针数组

请看下面2个表达式

int *p[3];
int (*p)[3];

前面是指针数组,后面是数组指针
一张图你就懂了
这里写图片描述

int *p[3] 是这样看待的:
p[3]是第1部分,这显然是个数组,于是编译器为你分配一块内存,这块内存有3个坑,就是可以放3个变量。
int*是第2部分,他表明刚才提到的3个坑里放的变量是int *类型,即是指向int类型的指针,综上是指针数组。

int (*p)[3]是这样看待的:
(*p)是第1部分,这明显是一个指针变量,于是编译器为你分配一块内存,这个内存放着指针变量p。
int [3]是第2部分,这是一个int [3]类型变量,即这是一个能存放3个int类型变量的数组,而p是指向这个数组的指针,综上是数组指针。

为什么能这样分成第1部分、第2部分?请看下面这张表
这里写图片描述
这里写图片描述
这里写图片描述

可以看到()的优先级是比*高的,[]优先级最高,()第二,所以才能这样分成2部分看待。

讲到数组就补充下面知识点,看下图:
这里写图片描述

#include "stdio.h"
/*
1.直接对数组取址,代表整个数组地址&a 
2.数组名代表首元素地址 a == &a[0]
*/
int main()
{
	char str1[]="abc";
	char str2[]={'a','b','c'}; //相对于str1少'\0'
	char str3[]={"abc"}; //和str1等价
	char str4[]={'a','b','c','\0'}; //和str1等价
	int a[3];
	printf("str1 sizeof %d\n",sizeof(str1));
	printf("str2 sizeof %d\n",sizeof(str2));
	printf("str3 sizeof %d\n",sizeof(str3));
	printf("str4 sizeof %d\n",sizeof(str4));
	printf("a       %x\n",a);
	printf("a+1     %x\n",a+1);
	
	printf("&a[0]   %x\n",&a[0]);
	printf("&a[0]+1 %x\n",&a[0]+1);
	
	printf("&a      %x\n",&a);
	printf("&a+1    %x\n",&a+1);
}

gcc 编译出如下结果
这里写图片描述

再看下面复杂声明:

void *(*a[3])(int b);

分析:
查看上表,[]*优先级高,所以a先和[]结合,这是第1部分,所以他本质是数组,有3个坑。
再和*结合,声明了指针变量,就是说坑里放的是指针变量。
再看外层,坑里的指针变量指向了长成void * (f)(int b)这个样子的函数
综上,这是函数指针数组

二维数组指针

int a[4][5];
int (*p)[5] = a;

这里定义了一个二维数组a,而p是指向a的指针,把p叫做指向a的二维数组指针
准确来说p是指向包含5个int元素的一维数组,此时p的增加、减少是以它所指向的一维数组长度为单位。如下程序证明

#include <stdio.h>
int main()
{
	int*q=NULL;
	int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} };
	int (*p)[4] = a;
	printf("1-%d\n", sizeof(*(p+1)));
	printf("2-%d\n", sizeof(int));
	printf("3-%d\n", sizeof(*(p+1)+0));
	printf("4-%d\n", sizeof(q));
	
	for(int i=0;i<3;i++)
	{
		for(int j=0;j<4;j++)
			printf("%d ",*(*(p+i)+j));
		printf("\n");
	}
	printf("\n");
	for(int i=0;i<3;i++)
	{
		for(int j=0;j<4;j++)
			printf("%d ",a[i][j]);
		printf("\n");
	}
	return 0;
}

结果
在这里插入图片描述
上面程序是在64位系统运行的,从4可以看出一个指针变量占用8字节,int类型占用4字节,
sizeof(*(p+1))=16,可见取到的是一行内容,因为int是4字节,一行有4个int类型,p+1指向下一行,p-1指向上一行
但是sizeof(*(p+1)+0)为什么为8呢,这里 *(p+1)表示第 1 行第 0 个元素的地址,加0,就是再偏移0单位,明显这里是地址,不再是一行内容,所以当然sizeof为8。
所以:
*(p+1)单独使用时表示的是第 1 行数据,放在表达式中会被转换为第 1 行数据的首地址,也就是第 1 行第 0 个元素的地址,因为使用整行数据没有实际的含义,编译器遇到这种情况都会转换为指向该行第 0 个元素的指针;就像一维数组的名字,在定义时或者和sizeof、& 一起使用时才表示整个数组,出现在表达式中就会被转换为指向数组第 0 个元素的指针。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值