===================================================================================================================================
[0]导言 关于C的数组和指针
===================================================================================================================================
在C语言的学习过程中,我曾听到不止一个老师对我说过,
“数组是一个指针常量”
“二维数组就是一个指针数组,所以你可以把n维数组直接赋值给n级指针,多维数组会附加大量的指针变量耗损内存”
而实质上,这些都是基于直觉的想当然的想法,我想,这也是大多数C语言初学者的思维误区(如果你有几万行的代码量还这么想我建议你把每天睡午觉的时间匀出来看会儿《C专家编程》和《C指针与陷阱》)。
在开始分析C的数组与指针之间的关系与区别之前,首先容我简单回顾下C的指针和数组这两种数据类型(或者说数据结构)的相关基础知识。 那么,首先请容许将C提供的数据类型分为三种:
- 简单类型(内置的数值类型如int,double等)
- 复合类型(用户自定义的如struct,union类型)
- 复杂类型(前两种类型配合修饰符组成的新类型,指针和数组属于该种)。
这里我们只讨论复杂类型,C提供的格式修饰符有三个:
- () 代表函数
- * 代表指针
- [] 代表数组
复杂类型由简单类型和以上修饰符组合而成,用于一些简单类型的变量不能或者难以实现的特殊功能。下面是一些复杂类型定义变量的例子(0-0):
int foo(); //这是一个函数的声明式,不是一种数据类型,仅作对比
int (*fun_ptr)(); //这是一个指向返回值为
int,参数列表为空的函数的函数指针
int *ptr; //这是指向一个int类型的一个指针(一级指针)
int **pptr; //这是一个关于int二级指针
int array[ 10 ]; //这是一个int数组(一维数组)
int array_2[ 10 ][ 5 ]; //这是一个int二维数组
int* ptr_array[ 10 ]; //这是一个储存指向int类型的指针的数组
int (*array_ptr)[ 5 ]; //这是一个指向数组的指针(即数组指针,之后会讨论)
其中,指针是一种储存内存地址的数据类型,一般的理解为指向某个数据的数据类型;而数组则是用于储存一组相同类型的变量的数据类型,可以看做一个变量的集合。这里,指针之所以叫做复杂类型,就是指针实际储存了两个信息:指向的数据类型和指向变量所处的内存地址(其中void*是不包含类型信息的)。相比简单类型,指针和数组可以执行下标(value[n])和解引用(*value)操作,可以通过对指针和数组变量执行这两种操作取得指针所指内存的变量或者数组内部的元素。(0-1):
int value = 0;
int* pointer = &value;
int array[ 10 ] = { 0 };
此处array就是一个储存了10个int类型变量的一个集合,如果我们使用array[n](n从0到9)则会获得array这个数组变量第n+1个变量(取得是左值(不知道什么是左值和右值得请忽略))。而pointer则是一个指向int变量的指针,*pointer则会取得指向的变量,等同于直接使用value。
同时,指针和数组也可以执行简单的算数操作(与整数加减),比如pointer+1可以获取&value加上sizeof(int)的地址值。而对于array+2则是获取array的第三个元素(array本身作为右值是数组首元素的地址)。这些便可以说是数组和指针的基本知识,那么下面我们就开始讨论我们要弄清楚的是什么样的问题。
===================================================================================================================================
[1] 开场的一维数组和一级指针
===================================================================================================================================
首先在上面我也讲到了,数组和指针都是复杂数据,但他们是两种完全不同的数据类型,几乎可以说完全没有关系。数组负责储存一组相同类型的变量,指针负责储存指定类型变量的内存地址,通过数组和指针我们都可以间接的访问到数据本身,但他们本质是不同,数组是一块复合的数据结构,你甚至可以把它理解成一个特殊结构体,数据成员就是一组相同类型的变量,且内存空间是连续的(为何这么说后面会解释);而指针则是一个储存内存地址的变量,本质还是一个变量。
那么是什么造成我们拥有“一维数组就是一级指针常量”的概念