第七章 函数(4)函数和二维数组

(四)函数和二维数组

1.说明

    对于二维数组,与它对应的其实是指向整个数组的指针,因此,我们一般用两种方法来访问它,一种是定义数组名,来两次解除引用,也就是使用[]运算符;另一种方法是定义一个指向数组的指针来访问。如果需要编写二维数组作为参数的函数,那么需要使用的是指向数组的指针,因为数组名被当成是地址,而地址需要使用指针参数来进行访问。此时,正确声明指针就至关重要了,有一点需要说明的是在函数形参的声明中,如果声明的是一个数组,不管是二维也好,一维也好,也不管是常量数组还是指针数组,我们传递给它的实参都只是一个地址,不是真正的数组。比如参数中有int a[5],表示的是传递的时候我们用一维数组的第一元素的地址作为实参(也就是数组名对应的地址);再比如int b[][20],表示是用指向有20个元素的数组的地址作为参数,也就是二维数组名作为参数。

    对于数组名后面紧随着的中括号,比如上面的int a[5]和int b[][20]中a后面和b后面第一个中括号,仅仅表示声明的是一个指针,中括号中的数字是多少并没有什么不同,它们等同于这样的声明int *a和int (*b)[20]。但是第二个中括号中的数字是有影响的,它表示指针指向的元素实际是一个数组,而数组的大小就是第二个中括号中的数字。

    对于二维数组,或者说指向数组的指针(本质上是指向整个数组地址的指针),不能使用const来修饰。

2.两种方法

    第一种方法:指向数组的指针,等价于二维数组名。比如这样一种形参定义int a[][20],这表示我们的a是有20个元素构成的数组的第一个数组的地址,我们可以用a[i]来表示索引为i的20个元素的数组名。这和这种声明是一样的:int (*a)[20],表示定义了一个可以指向有20个元素的数组的指针,a是指向数组名的指针(注意不是指向数组第一个元素的指针),a[i]同样表示索引为i的20个元素的数组名,*(a+i)和a[i]是等价的。

    第二种方法:数组名。采用如下的定义:int a[][20]或int a[2][20],表示定义了二维数组,需要传递一个指向有20个元素的数组的地址。

3.指针数组和数组指针

    指针数组指的是由指针构成的数组,比如int *p[2];表示的就是两个指向int类型的指针构成的数组;而数组指针指的是指向数组第一个元素地址的指针,比如int (*p)[2];表示的就是指向有两个int元素的数组的指针。指向一维数组的指针和二维数组名实际上是一个东西,都是指向一个一维数组的地址,不同的是指针可以改变是一个变量,而二维数组名是一个常量,不能改变。在形参的声明中,数组或二维数组指的不是数组,而是一个指针,在函数内部,这个形参是可以改变值的。只有形参的声明可以使用数组名表示指针,二者没有区别,在其他地方,数组名和指针还是有区别的,数组名相当于指针常量,也就是只能指向一个位置的指针。

4.函数和c风格的字符串

    c风格字符串无法直接传递,因此当字符串作为函数的参数的时候,不管是字符数组名,指向字符串的指针,还是字符串字面值,其实传递的都是地址,这跟一维数组的情况是一样的,只不过这个数组里面储存的是以\0结尾的c风格字符串。

    函数无法返回字符串,但是可以返回字符串的地址,这样做的效率更高。但是,如果函数内的字符串的内存是用new创建的,那么函数内是没有将内存释放的,我在函数外面调用函数之后,才可以看到这些字符,那么,我们必须在函数外面显式地delete掉这些new创建的内存。

    常量指针和指针常量:常量指针指的是指向常量的指针(或者是相对于这个指针是常量),而指针常量指的是指针本身是常量,不能够改变。常量指针的声明是这样的int b=2;const int *a=&b;这样声明的指针无法更改指向的位置的内容,而只能引用它,常量指针可以更改指针指向的对象 ,但无法更改。指针常量的声明是这样的,int b=2;int * const p=&b;这样声明的指针只能够初始化一次,不能改变指针指向的对象,但我们可以改变指针指向的对象的内容。有时候也可以常量指针和指针常量一起使用,比如const int *(const p)=&b;这样的指针既只能指向一个int数据,又不可以更改这个数据。


你可能感兴趣的:(第七章 函数(4)函数和二维数组)