数组类型,数组指针类型,数组指针类型变量

1.数组的基础知识复习

1.1 数组的定义:

  1. 从数组元素的角度:相同类型的变量的有序集合;
  2. 从内存角度:一段连续的内存空间;

1.2 数组的初始化:

  1. 可以指定长度,也可以不指定长度;
  2. 可以直接用赋值符号给初值,或者用memset函数重置内存块;

int tmp0[] = {1,3};
int tmp1[20] = {0};//在编译时就将数组元素置为0
memset(tmp1,0,sizeof(tmp1));//显示的将数组代表的内存空间置为0

1.3 关于数组的易错点:

  1. 数组首元素地址和数组地址是两个不同的概念,要严格区分:
    相同点:数组首元素地址和数组地址在数值上是相同的;
    不同点:表示方法不同,含义不同,用 int tmp[20] = {0}; 来举例:
    数组首元素地址:tmp1,即数组名表示的就是数组首元素地址,是一个常量,不能做左值,但是数组元素是变量,如tmp[2], tmp[3];
    数组首元素tmp[0]的类型是int,所以数组名tmp是int大小栈空间地址。
    tmp1 + 1 表示指针移动了一个数组元素长度,4个字节;
    数组地址:&tmp1,因为数组tmp[20]的类型是int[20],所以整个数组地址&tmp是20*4这段栈空间的地址。
    &tmp1 + 1 表示指针移动了一个数组长度,20*4个字节;
  2. 指针可以进行加减算术运算,加减的基本单位是sizeof(指针所指向的数据类型)。
  3. 对数组的数组名进行取地址(&)操作,得到的是整个数组的地址,后面介绍数组指针类型变量时会详细讲解。
  4. 对数组的数组名进行sizeof运算符操作,其值为整个数组的大小(以字节为单位),sizeof(tmp) = 20*4, sizeof(&tmp1)结果为一个指针长度。
  5. 实际上并不存在多维数组,所谓的多维数组本质上是用一维数组模拟的。

如果能将二维数组按一维的方式输出,那么就可以证明上述结论。
以二维数组int tmp1[][3] = { {1,2,3},{4,5,6}};为例

 printfArray(int* array,int num)
 {
    
    
 	int i = 0;
 	for(;i < num;i++)
 	{
    
    
 		printf("%d\n",array[i]);
 	}
 }
#include <stdio.h>
int main()
{
    
    
 int tmp1[][3] = {
    
    {
    
    1,2,3},{
    
    4,5,6}};
 int len = sizeof(tmp1) / (sizeof(int) * 3);
 printfArray((int*)tmp1,len);

  1. 数组作为函数形参时会退化为指针。

可以通过在函数里面和函数外面用sizeof计算数组名的大小来证明,因为传进去
的数组名在函数里面退化为指针,sizeof(数组名)为一个指针的大小,通过第四条在函数外面sizeof(数组名)为整个数组的大小。

2.数组的数据类型

数据类型的本质是一段固定大小的内存空间别名。

数组的数据类型是复杂数据类型,不属于c语句标准规定的基础数据类型,由数组元素类型和数组大小组成;
int tmp1[20] 的数据类型是int[20]

定义特定数组类型的数组变量:

例如我们想定义float[10]类型的数组:
typedef float(Array)[10]
Array tmp1;//tmp1就是float[10]类型的数组,等价于float tmp1[10]

3. 数组指针类型

怎样定义一个指针来指向数组(一维)呢?我们有三种表示方法。
第一种方法:
在基本数据类型中我们定义一个指向一个变量的指针,通常是在变量类型后面加‘*’,如int* p,同理我们也可以按这种方法表示数组指针类型;

typedef float(ArrayType)[10]; //数组类型ArrayType
ArrayType tmp2;
ArrayType* ptr = &tmp2;//数组指针ptr就指向了数组tmp2

第二种方法:
直接用typedef定义数组指针类型

typedef float(ArrayType)[10];
ArrayType tmp2;

typedef float(*ArrayPoint)[10];//数组指针类型ArrayPoint
ArrayPoint ptr;//数组指针类型的变量 ptr
ptr = &tmp2;

#include<stdio.h>
void main()
{
    
    
	typedef int(ArrayType)[5];
	ArrayType tmp0 = {
    
    0};
	printf("数组首元素地址:%p \n",tmp0);
	printf("数组地址:%p \n",&tmp0);
	printf("tmp0 + 1 地址:%p \n",tmp0 + 1);
	printf("&tmp0 + 1地址:%p \n",&tmp0 + 1);

	typedef int(*ArrayPoint)[5];
    ArrayPoint ptr;
    ptr = &tmp0;
    
	int i = 0
	for(;i < 5;i++)
	{
    
    
		*(ptr++) = i;
		printf("%d \n",tmp0[i]);
	}

}

第三种方法:
更常用的,直接定义数组指针变量,要和数组指针类型区别开来,和数组指针类型变量本质一样,只是简化了写法。

// typedef float(ArrayType)[10];
// ArrayType tmp2;

> float tmp2[10];
> 
> //typedef float(*ArrayPoint)[10];//数组指针类型ArrayPoint
> //ArrayPoint ptr;//数组指针类型的变量  ptr
> float (*ArrayPoint)[10];
> //ptr = &tmp2;
> ArrayPoint = &tmp2;

4.多级指针和多维数组的关系

这里以二维数组char a[3][2] 来说明

a[i][j]数组第i行j列元素地址 &a[i][j] *(a +i) + j a[i] + j
a[i][j]数组第i行j列元素的值 a[i][j] *(*(a +i) + j) *(a[i] + j )
a a + i *(a +i) *(a +i) + j a[i] a[i] + j
含义 二维数组首元素a[0]地址,&a[0] 二维数组第i个元素a[i]地址,
a +i = &a[i]
二维数组第i个元素a[i](也是有2个元素的数组)
的首元素地址,&a[i][0]
二维数组第i个元素a[i](也是数组)的第j个元素地址,
&a[i][j]
同*(a +i) 同*(a +i) + j
类型 char (*a)[2]
即二维数组首元素类型
char (*a)[2]
即二维数组第i个元素类型
char* char* char*
char [2]
char*
指针 2级指针
&a[0] = &(&a[0][0] )
2级指针
&a[i] = &(&a[i][0] )
一级指针
a[i] = &a[i][0]
一级指针
&a[i][j]
同*(a +i) 同*(a +i) + j

在这里插入图片描述

#include <stdio.h>
int main()
{
    
    
	int tmp0[3] = {
    
    1,2,3};
	printf("--------------一维数组的数组名------------------");
	printf("tmp0:%p\n",tmp0);
	printf("&tmp0[0]:%p\n",&tmp0[0]);//&(tmp0[0])
	printf("tmp0 + 1:%p\n",tmp0 + 1);//&(tmp0[1])
	
	printf("-----------一维数组-与--数组指针-----------------");
	//指向数组的指针可能是指向整个一维数组的指针,或者是指向二维数组的一个元素
	int (*ptr0)[3] = NULL;
	ptr0 = &tmp0;//这里指向数组的指针是指向整个一维数组的指针
	printf("ptr0 :%p\n",ptr0 );
	printf("ptr0 + 1:%p\n",ptr0 + 1);

	printf("*ptr0 :%p\n",*ptr0 );//一维数组的首元素地址
	//*ptr0 = *(&tmp0) = tmp0 = &(tmp0[0])      **ptr0 = tmp0[0]
	printf("*ptr0 + 1:%p\n",*ptr0 + 1);
	
	printf("--------------二维数组的数组名------------------");
	int tmp1[][3] = {
    
    {
    
    1,2,3},{
    
    4,5,6}};
	printf("tmp1:%p\n",tmp1);//=&tmp1[0]
	printf("tmp1 + 1:%p\n",tmp1 + 1);//=&tmp1[1]
	
    printf("tmp1[0]:%p\n",tmp1[0]);//tmp1[0]是二维数组的首元素
    //也是有3个元素的数组,tmp1[0]可以看做为数组(tmp1[0])[3]的数组名,
    //数组(tmp1[0])[3]首元素(tmp1[0])[0]的地址,&tmp1[0][0]
	printf("tmp1[0] + 1:%p\n",tmp1[0] + 1);//&tmp1[0][1]
	
	printf("*tmp1:%p\n",*tmp1);//*tmp1 = *(&tmp1[0]) = tmp1[0] = *(tmp1+0) + 0 = &tmp1[0][0] 
	printf("*tmp1 + 1:%p\n",*tmp1 + 1);//=&tmp1[0][1] = *(tmp1 +0) + 1
	printf("*(tmp1 + 1):%p\n",*(tmp1 + 1));//&tmp1[1][0] = *(tmp1 + 1) + 0

}

参考文章:图解c/c++多级指针与“多维”数组
《C Pimer Plus 第六版》10.7 指针和多维数组

猜你喜欢

转载自blog.csdn.net/u014157109/article/details/119629986