(1)类型名称后面加上解引用修饰符*,就成为了某某类型的指针。指针的值就是内存地址,对指针的操作就是对内存地址的操作。
因为分配内存的持久性和灵活性,所以导致指针更加灵活,只要拥有指针,那么就能操作那块内存!
指针本质上是一个数字,内存地址本质上也是一个数字,只不过这个数字代表着一段可存放数值的内存。
指针的值可以是一块用malloc分配的内存的首地址,也可以是一块由C语言标准类型定义的变量的首地址。还可以是,只要有内存的地方,就能用指针的值代表!所以,指针本质上是和内存地址相互映射的,指针本质上是没有类型!但指针可以作为任何类型使用!
注:若程序员要使用指针,必须清晰知道指针所指向的内存的值究竟是什么,所指向的内存的大小究竟有多少!
如:
int* ptr = (int*)malloc(sizeof(int));
double* ptr2 = (double*)ptr;
char* ptr3 = (char*)ptr2;
char* ptr4 = (char*)ptr;
struct myStruct
{
int a;
};
struct myStruct* pStruct = (struct myStruct*)ptr; //可以转换为一个结构体的指针类型。
int myInt = (int)ptr; //直接赋值给整型变量也可以。
指针没有类型,每一个指针的大小都由计算机决定,若计算机是32位的,那么计算机最大的内存是2的32次方位,也就是4G,那么指针的大小就是32位,即4个字节。若计算机是64位的,那么计算机最大的映射内存是2的64次方位,可映射内存就很大很大,其指针大小也是64位,即8个字节。现在使用的指针,都是32位的指针,即使是现在的64位机器,也是32的内存地址。
(2)数组是一段连续的内存地址。数组下标从0开始,一直到数组大小减一的下标。数组有一维数组、二维数组、三维数组等等n维数组。
如【int myArray[10];】这里定义了存放连续10个int类型数据的数组。这种方式和在连续空间里定义10个int变量的意义是一样的。
如【int myArray[10][6];】这个是二维数组,第一维是10,第二维是6,其实,从编译器看,只要不是最后的维度,都存放着一个32位指针变量,这里第一维度是10个指针,第二维度才是真正的6个int类型数据内存。显然,这里是存了10个一维数组,每个一维数组都连续存储了6个int类型的变量。
如【double myArray[10][9][8];】这里很显然,最后一个维度8,才是真正存储double类型数据变量的,其他维度都存储着32位的指针地址。第一维是10,表示存了10个指针,每个指针指向一个一维数组,这种一维数组维度都是9,每个维度里都存放着指针,而这些指针都指向一个一维数组,每个数组维度都是8,连续存储了8个double类型的变量。
注:虽然数组里面存储了指针,但数组的内存地址必然是连续的,如【int myArray[10][6]】这里存储了10个6维的一位数组,每个6维的数组都在连续的内存地址上连续存放,存放完一个6维的数组,又连续继续存放第二个6维的数组。。。直到存放完所有的10个一维数组。