目录
数组的理论知识
基本定义
从元素类型角度看,数组是相同类型的变量的有序集合测试指针变量占有内存空间大小;从内存角度看,数组是互相联系的一大片内存空间,如图。
数组的初始化
分为隐式指定和显式指定两种,其中:
隐式指定,相当于不指定数组长度,为:
int b[] = {1, 2};
显式指定,相当于指定数组长度,为:
int a[10] = {1,2}; //其他初始化为0
数组名的技术盲点
1)数组首元素的地址和数组地址是两个不同的概念。
2)数组名代表数组首元素的地址,它是个常量。
解释如下:变量本质是内存空间的别名,一定义数组,就分配内存,内存就固定了。所以数组名起名以后就不能被修改了。
3)数组首元素的地址和数组的地址值相同(等)。
数组类型
数组的数据类型属于复杂数据类型,不能单纯的按以前的但看数据类型来觉得其内存的分配的长度。
数组类型:
typedef int(MYINT5)[5]; //int 相当于定义了一种类型
typedef float(MYFLOAT10)[10];
数组定义:
MYINT5i Array; int array[5];
MYFLOAT10fArray
下面来定义一个数组类型:
进行主函的编写,
void main()
{
int i = 0;
//定义一个数组类型
typedef int MyArrayType[5]; //int
int a;
MyArrayType MyArray; //int MyArray[5];
for (i = 0; i < 5; i++)
{
MyArray[i] = i + 1;
}
for (i = 0; i < 5; i++)
{
printf("%d \n", MyArray[i]);
}
printf("hello...\n");
system("pause");
return;
}
运行结果如下:
数组指针
以"int a[10]"为例,知:
1.数组名是数组首元素的起始地址,但并不是数组的起始地址;2.通过将取地址符&作用于数组名可以得到整个数组的起始地址
//定义数组指针 有两种
1)通过数组类型定义数组指针:
typedef int(ArrayType)[5];
ArrayType* pointer;
2) 声明一个数组指针类型 typedef int (*MyPointer)[5];
MyPointer myPoint;
3)直接定义:int (*pointer)[n];
pointer 为数组指针变量名
type 为指向的数组的类型
n 为指向的数组的大小
注意这个地方是type类型(比如 int (*pointer)[10])
下面进行举例说明,我们都知道"int *p = NULL"定义了一个空指针p,那么怎么将这个指针指向已定义的数组类型呢?
演示如何通过数组类型 来定义一个指向数组类型的指针变量。
//C语言中最难的语法部分
void main()
{
int i = 0;
//定义一个数组类型
typedef int MyArrayType[5]; //int
//定义了一个数组类型的指针
MyArrayType *pArray = NULL;
int a[5];
//如何定义一个数组类型指针
{
int a1;
int *p1 = NULL;
p1 = &a1; //对变量取地址,赋给指针
}
pArray = &a;
printf("hello...\n");
system("pause");
return;
}
如上代码中进行的定义pArray,是一个指向数组类型的指针变量,其定义方法,和普通的指针定义方法没有什么不一样的,上代码中拿普通指针p1的定义方式和其做对比,来进行推演。
那么在定义好之后,如何通过指针来控制内存块呢?下面继续推演:
接着如上思路,变量a本身是数组的一级指针,那么当"&a"的时候,变成了数组的二级指针了。那么对于pArray来说,须先把从“&a”处取的值,变成一级指针,然后再进行控制内存:
//我通过数组指针的方式来操作a[5]这块内存
//注意!这个地方比较难!
for (i=0;i<5;i++)
{
(*pArray)[i] = i + 1; //相当于 a[i] = i + 1;
}
别想那么多,特别是别跟前面说a保存的是首个元素的地址,&a是取的数组的首地址;就只想着pArray是通过&a得到的,而操作内存空间是通过a来进行的,所以,要进行还原,所以才有了(*pArray),其效果等同于a。
下面把其打印出来:
for (i = 0; i < 5; i++)
{
printf("%d \n", (*pArray)[i]);
}
下面再做一步引申:
根据以上的推演,我们已经得出了数组类型了,并且根据数组类型我们可以控制内存,下面我想直接定义一个数组指针类型。
void main()
{
//这样是定义了一个类型,这个类型是数组类型
typedef int MyArrayType[5]; //int
//下面想定义一个类型,这个类型是想让它是数组指针类型,它本质是个指针类型
typedef int(*MyPArrayType)[5];
system("pause");
return;
}
括号内部的部分优先级高,所以,优先考虑括号内部的部分,上面代码中(*MyPArrayType),带有*号,说明其是个指针,其上表明,定义了一个指针类型,这个指针类型是用来指向一个数组,就这个意思。
演进过程:首先,是定义了一个类型(int),然后,再定义了一个指针类型(*MyPArrayType),然后,继续定义了一个指向数组的指针类型(*MyPArrayType)[5]。
注意!注意!注意!这个时候就可以解释之前的多维数组的步长问题了,因为在多维数组中,从上一维向下一维度扩展,都是需要如上面所进行的过程的,都是要指定所指向的数组的,上面的那个指向的数组长度为[5],如果是在多维数组中下一维的数组长度就是指向上一维的数组指针每次移动时候的步长。(我不知道我叙述清楚没有,的确有点绕— —||)
下面接着,来看看数组指针类型来操作内存:
int b[5];
{
int b1 = 0;
int *pb1 = &b1;//等同于,变量取地址传给指针
}
myPoint = &b; //变量取地址传给指针
//如何通过这个来操作内存
for (i= 0;i<5;i++)
{
(*myPoint)[i] = i + 1;
}
for (i=0;i<5;i++)
{
printf("%d ", (*myPoint)[i]);
}
对比之前的用数组类型和用数组指针类型两种定义方式:
void main()
{
{
//定义一个数组类型
typedef int MyArrayType[5]; //int
//定义了一个数组类型的指针
MyArrayType *pArray = NULL;
}
{
//下面想定义一个类型,这个类型是想让它是数组指针类型,它本质是个指针类型
typedef int(*MyPArrayType)[5];
MyPArrayType myPoint; //int b[5];
}
}
那这两种方式定义指针变量还是比较麻烦的,C++编译器的先驱们,在设计编译器的时候,就考虑到了一种更简单的方式:
直接定义的方式:
int (*pointer)[n];
pointer 为数组指针变量名
type 为指向的数组的类型
n 为指向的数组的大小
举例说明:
void main()
{
int c[5];
int(*mypArrayPoint)[5]; //告诉编译器,立马分配4个字节内存
mypArrayPoint = &c;
}
这样就通过非常简单的方式来定义指针变量。而不像上面的那么冗杂。
总体代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef struct _Teacher
{
char name[20];
int age;
}; Teacher;
void main11()
{
int i = 0;
//定义一个数组类型
typedef int MyArrayType[5]; //int
int a;
MyArrayType MyArray; //int MyArray[5];
for (i = 0; i < 5; i++)
{
MyArray[i] = i + 1;
}
for (i = 0; i < 5; i++)
{
printf("%d \n", MyArray[i]);
}
printf("hello...\n");
system("pause");
return;
}
//C语言中最难的语法部分
//演示如何通过数组类型 来定义一个指向数组类型的指针变量。
void main12()
{
int i = 0;
//定义一个数组类型
typedef int MyArrayType[5]; //int
//定义了一个数组类型的指针
MyArrayType *pArray = NULL;
int a[5];
//如何定义一个数组类型指针
{
int a1;
int *p1 = NULL;
p1 = &a1; //对变量取地址,赋给指针
}
pArray = &a;
//我通过数组指针的方式来操作a[5]这块内存
//注意!这个地方比较难!
for (i=0;i<5;i++)
{
(*pArray)[i] = i + 1; //相当于 a[i] = i + 1;
}
for (i = 0; i < 5; i++)
{
printf("%d \n", (*pArray)[i]);
}
printf("hello...\n");
system("pause");
return;
}
void main13()
{
int i = 0;
//这样是定义了一个类型,这个类型是数组类型
typedef int MyArrayType[5]; //int
//下面想定义一个类型,这个类型是想让它是数组指针类型,它本质是个指针类型
typedef int(*MyPArrayType)[5];
MyPArrayType myPoint; //int b[5];
int b[5];
{
int b1 = 0;
int *pb1 = &b1;//等同于,变量取地址传给指针
}
myPoint = &b; //变量取地址传给指针
//如何通过这个来操作内存
for (i= 0;i<5;i++)
{
(*myPoint)[i] = i + 1;
}
for (i=0;i<5;i++)
{
printf("%d ", (*myPoint)[i]);
}
system("pause");
return;
}
void main()
{
int c[5];
int(*mypArrayPoint)[5]; //告诉编译器,立马分配4个字节内存
mypArrayPoint = &c;
{
//定义一个数组类型
typedef int MyArrayType[5]; //int
//定义了一个数组类型的指针
MyArrayType *pArray = NULL;
}
{
//下面想定义一个类型,这个类型是想让它是数组指针类型,它本质是个指针类型
typedef int(*MyPArrayType)[5];
MyPArrayType myPoint; //int b[5];
}
system("pause");
}