在c++中,数组是一种最基本的数据结构。
我们提起数组时,都是默认数组为定长数组。
1.数组的声明
定义一维数组的一般方式为
类型名 数组名[常量表达式];
定义二维数组的一般方式为
类型名 数组名[常量表达式1][常量表达式2];
注意:在定义数组长度时,常量表达式可以是常量、常变量和符号常量,但是不能包含变量。因为这里的数组是定长数组,数组长度一旦确定便不能再进行修改,所以常量表达式必须是确定且固定的值。
多维数组可以被理解为数组的数组。上面的二维数组可以理解为一个一维数组,这个一维数组的每个元素还是一个数组而已。
在c++中多维数组的存放是按照行进行存储的,在内存中先存储第一行的元素,再存储第二行的元素。
首先对于函数的运行进行简单的介绍
高级语言编写的程序是存储在辅存中,程序中的函数自然也是存储在辅存中。当程序执行程序时,程序就成为了进程,操作系统以进程为单位分配资源。在进程中,当函数未被执行时,操作系统并不会为函数分配内存。而当函数被调用之后,操作系统会为被函数开辟新的内存空间并运行。所以函数被调用时,并不是和调用函数在同一块内存区域。函数被调用时需要为函数传递参数,参数传递的方式有三种,值传递,引用传递和指针传递。
值传递的方式传递参数,其实是在为被调用函数分配内存空间后,将实参拷贝到被调用函数运行的内存空间中并进行赋值。这样函数运行时,实参和形参在两块相互独立的运行空间中,是两个相互独立的个体。所以在函数运行时,形参的改变并不会影响实参的变化。当函数被调用结束后,系统会释放和回收这块内存空间,被调用函数运行的结果会通过return语句返回,其实就是将被调用函数运行空间中的运行结果拷贝到调用函数运行的内存空间中并进行赋值。
若函数的参数是通过指针传递和引用传递的方式传递参数,当函数被调用后尽管和调用函数运行在两块不同的内存空间,但都是通过指针来操作调用函数内存区域中的变量值。所以引用传递和指针传递的函数中,形参的改变均会影响实参。
由上可知,被调用函数与调用函数并不是在同一块内存区域中运行。无论被调用函数的参数传递是采用何种传递方式,在新开辟的内存区域中都会进行参数的赋值(指针传递和引用传递也是通过赋值来建立的)。
回归今天的主题
2.数组元素做函数实参
数组元素可以用作是函数的实参,与用变量作为函数的实参一样,将数组元素的值传递给形参变量即可。此时采用的是值传递方式。
首先谈谈数组名
数组被声明之后,编译器便在内存中为数组分配了一块连续的内存空间。若在声明时未指定数组初始值,编译器便为数组元素赋初值。当维数组分配了一块连续内存空间后,此连续内存空间的首地址,也就是首元素的地址会被存储在数组名中。也就是数组名其实类似于是一个指针变量,这个指针变量中存储的是数组所在的连续内存空间的首元素的地址,也是连续内存空间首字节的地址。所以数组名并不是代表数组的全部元素。但同时,数组被分配后便不再改变,所以数组名中的地址不可改变。
综上所述:数组名代表了数组所在连续内存空间的地址,也是连续内存空间中首元素的地址。
但是数组名的利用分为两种情况,当数组名被直接使用时,数组名代表的就是整个数组,例如将数组名传递给运算符sizeof()时,返回的就是整个数组所占内存的大小。但是数组名当作参数传递时,数组名就会退化为指针,如下,数组名在被当作形参时,数组名为指针变量赋值时,都退化为了指针。
3.当数组名被当作函数实参时
函数返回值类型 函数名(数组中元素类型名 形参数组名[]){};
注意:形式参数表中,形参数组名后的[]只说明这里要传入的是数组名。这和我们调用无参函数一样,函数在被调用时,即使不要传入参数,也要加上函数名后面括号以表明这是一个函数。
1 //函数 2 void selected_sorted(int array[], int nums) 3 { 4 //函数实现 5 } 6 //定义数组 7 int nums[30]; 8 9 10 //函数调用 11 selected_sorted(nums, 30);
数组名关于指针变量的使用
下面语句中,p = nums语句是吧nums数组的首元素地址赋值给指针变量p,此时数组名退化为了指针。
1 int nums[30]; 2 int *p 3 4 //下面两条语句等价 5 p = nums; 6 p = &nums[0];