数组篇

一维数组

  1. 说明格式:类型 标识符[表达式];
  2. 访问数组:(1)下标形式;(2)指针形式。两种方式实例如下:

/**********************************************************
* 函数:AccessArray
* 描述:访问数组的方式
* 参数:无
* 返回:无
* 备注:1.下标 2.指针形式
**********************************************************/
void AccessArray(void)
{
    int i;
    int* p;
    static int a[5] = { 1,2,3,4,5 };//定义一个静态的int类型数组

    //下标访问
    cout << "以下标方式访问数组" << endl;
    for (i = 0; i < 5; i++)
    {
        cout << "a[" << i << "]=" << a[i] << " ";
    }
    cout << endl;

    //指针形式访问-1
    cout << "以指针方式访问数组-1" << endl;
    for (i = 0; i < 5; i++)
    {
        cout << "a[" << i << "]=" << *(a+i) << " ";
    }
    cout << endl;

    //指针形式访问-2
    cout << "以指针方式访问数组-2" << endl;
    p = a;
    for (i = 0; i < 5; p++,i++)
    {
        cout << "a[" << i << "]=" << *p << " ";
    }
    cout << endl;
    //数组元素的地址
    cout << "数组元素的地址:" << endl;
    p = a;
    for (i = 0; i < 5; p++, i++)
    {
        cout << "a[" << i << "]的地址:" << p << endl;
    }
}

运行结果:
数组访问
此处应该注意:1. 数组名a是一个常量,a==&a[0],所以并不能做自加运算a++,只能将其值赋给同类型的指针变量*p之后,p才能自加。如果没有这个指针变量,只能通过 *(a+i)形式访问。2. 从数组各个元素的地址可见,每个元素的地址相差sizeof(int)=4,数一维组元素在内存中的排列是顺序排列,每个元素地址相差大小等于其元素类型所占空间的大小。3. 数组访问超出界限的话编译器不会作检查,应注意。

指针数组

定义

说明形式:类型 *标识符[表达式];例如:
int *pi[3];
char *pf[5];
指针数组和基本类型如int类型的数组区别在于存储的数组类型不同,其存储的是指针类型。
注意:int *pi[3]不能写成int (*pi)[3];int *pi[3]中的pi是一个指针数组,但是
int (*pi)[3]中pi是一个指向一维数组(长度为3)的指针。可以根据符号的优先级来解释:int *pi[3]中,[]符号有限级比 * 符号的优先级要高,所以[]首先与pi结合,pi首先是一个数组,然后在与左边结合,说明数组元素的数据类型为int *;对于int (*pi)[3],()符号的优先级比[]符号的优先级高,所以 * 首先和pi结合,pi是一个指针,int以及[3]说明指针关联的数组类型,即是一个3长度int类型的一维数组。

指向基本数组类型的指针数组

基本数据类型如int、char等这些数据类型,如上的int *pi[3]既是一个指向基本数组类型的指针数组,顾名思义就是数组里面存放的是基本数据类型的地址(指针)。可以此种类型的数组用来管理变量地址。

指向数组的指针数组

可以类推,指向数组的指针数组:即里面存放的是其他数组的指针,但是这些数组的类型必须是相同的,但是长度不必相同。其实可以将“指向基本数组类型的指针数组”看作是“指向数组的指针数组”的特例,当“指向数组的指针数组”中数组的长度为1是=时可看做“指向基本数组类型的指针数组”。“指向基本数组类型的指针数组”存储的是一个数组地址,可以通过这个地址访问到其数组的各个成员。举例如下:

/**********************************************************
 - 函数:PointerArray_PointArray
 - 描述:指向数组的指针数组
 - 参数:无
 - 返回:无
 - 备注:
**********************************************************/
void PointerArray_PointArray(void)
{
    int a[2] = { 1,2 };
    int b[3] = { 3,4,5 };
    int c[4] = { 6,7,8,9 };
    int* pi[3] = { a,b,c };//数组名就是数组的地址

    int i;

    //访问数组a
    cout << "访问数组a" << endl;
    for (i = 0; i < 2; i++)
    {
        cout << "a[" << i << "]=" << *(pi[0]+i) << " ";
    }
    cout << endl;
    //访问数组b
    cout << "访问数组b" << endl;
    for (i = 0; i < 3; i++)
    {
        cout << "b[" << i << "]=" << *(pi[1] + i) << " ";
    }
    cout << endl;
    //访问数组c
    cout << "访问数组c" << endl;
    for (i = 0; i < 4; i++)
    {
        cout << "c[" << i << "]=" << *(pi[2] + i) << " ";
    }
    cout << endl;
}

运行结果:
指向数组的指针数组

指向函数的指针数组

也可以类推,指向函数的指针数组:即数组里面存放的是函数指针(函数指针),就是一个函数的入口地址,通过函数指针可以调用函数。而函数中有函数名=函数指针=函数地址,所以数组中可以直接存入函数名,或者&函数名也可,它们都是相等的。

定义

  • 先用typedef定义函数类型,再定义数组
    如:typedef int FuncType(int ,int); FuncType *pFunc[3];
    这样就定义了一个指向FuncType类型函数的指针数组。
  • 直接定义,接上面,如:int (*pFunc[3])(int,int)。
  • 定义完之后再初始化数组。

示例

/**********************************************************
* 函数:PointerArray_PointFunc
* 描述:指向函数的指针数组
* 参数:无
* 返回:无
* 备注:
**********************************************************/
void PointerArray_PointFunc(void)
{
    int i;
    FuncType* PFunc[3] = {f1,f2,f3};

    for (i = 0; i < 3; i++)
    {
        PFunc[i]();//也可以写成(*PFunc[i])();
    }
}

/**********************************************************
* 函数:f1
* 描述:函数1
* 参数:无
* 返回:无
* 备注:调用时打印“调用函数f1”
**********************************************************/
void f1(void)
{
    cout << "调用函数f1" << endl;
}

/**********************************************************
* 函数:f2
* 描述:函数2
* 参数:无
* 返回:无
* 备注:调用时打印“调用函数f2”
**********************************************************/
void f2(void)
{
    cout << "调用函数f2" << endl;
}

/**********************************************************
* 函数:f3
* 描述:函数1
* 参数:无
* 返回:无
* 备注:调用时打印“调用函数f3”
**********************************************************/
void f3(void)
{
    cout << "调用函数f3" << endl;
}
//指向函数的指针数组
typedef void FuncType(void);
FuncType f1, f2, f3;
void PointerArray_PointFunc(void);

在main函数调用PointerArray_PointFunc函数,运行结果如下:
指向函数的指针数组

二维数组

定义和初始化

  • 说明格式:类型 数组名[表达式1][表达式2];
    表达式1:第一维长度,可视为矩阵中的行;
    表达式2:第二维长度,可视为矩阵中的列;
  • 初始化:可以省略最高维长度的说明。如:
  1. int a[2][3] = {{1,2,3},{4,5,6}};
  2. int a[2][3] = {1,2,3,4,5,6};
  3. int a[2][3] = {{1,2,3},{4,5}};//部分元素初始化
  4. int a[][3] = {{1,2,3},{4,5,6}};//省略最高维长度说明

访问

  1. 访问二维数组的形式也有两种:下标访问、指针访问。
  2. 下标访问理解比较简单,而理解指针的访问之前应该知道或者理解这么一句总结:数组结构是递归的,n维数组的每一个元素都是n-1维数组。一维数组可以看做多维数组的特例来理解,理解了一维数组的指针访问,二维数组的指针访问理解起来就容易多了。
  3. (1)首先一维数组的数组名本身是个常量指针,即不能对其作赋值运算,其等于第一个元素的地址,如对于int a[3],a==&a[0]。类推到二维数组,如int a[2][3],a==&a[0],虽然写法一样,但是表示的意义不一样。对于一维数组,a[0]就是一个int类型的元素,而对于二维数组,a[0]代表了一个以为数组。可以类比 到n维数组,a[0]代表了一个n-1维数组。所以a作为一个指针,对于不同维数的数组,其关联的类型不同:对于n维数组,a关联的是n-1维数组。其实可以简单理解为n维数组每个元素存储了n-1维数组的数组名,n-1维数组每个元素又存储了n-2维数组的数组名,这样一直递归下去,最终推到一维数组的情况停止。
    (2)在一维数组中,a+i==&a[i],在二维数组也成立,不过同(1)所述,其意义也不一样了。在一维数组里面,相邻的每个元素地址偏移量为sizeof(类型),对于二维数组,相邻元素的偏移量为(sizeof(类型)*一维数组长度),推广到n维数组,偏移量为(sizeof(类型)*n-1维数组的元素个数)。
  4. 指针访问和下标访问示例如下:
/**********************************************************
* 函数:TwodimensionalArray
* 描述:二维数组
* 参数:无
* 返回:无
* 备注:二维数组定义与访问示例
**********************************************************/
void TwodimensionalArray(void)
{
    int a[2][3] = { {1,2,3},{4,5,6} };
    int i,j;
    int(*p)[3];//定义一个关联类型为长度为3的整形数组的指针

    //各个元素的地址
    cout << "各个元素的地址" << endl;
    for (i = 0; i < 2; i++)
    {
        for (j = 0; j < 3; j++)
        {
            cout << "a[" << i << "]" << "[" << j << "]地址:" << &a[i][j]<< endl;
        }
    }
    cout << endl;

    //二维数组中的每个元素的地址
    cout << "二维数组中的每个元素的地址" << endl;
    for (i = 0; i < 2; i++)
    {
        cout << "第" << i << "个元素地址:" << a + i << endl;
    }
    cout << endl;

    //下标访问二维数组
    cout << "下标访问二维数组" << endl;
    for (i = 0; i < 2; i++)
    {
        for (j = 0; j < 3; j++)
        {
            cout << "a[" << i << "]" << "[" << j << "]数据:" << a[i][j] << endl;
        }
    }
    cout << endl;

    //指针访问二维数组-1
    cout << "指针访问二维数组-1" << endl;
    for (i = 0; i < 2; i++)
    {
        //对 *(*(a+i)+j) 的解释:
        //(a+i)指向的是存储一维数组地址(可理解为数组名)的地址
        //*(a+i)是将对应的数组名取出来
        //(*(a+i)+j)是一维数组每个元素的对应存储地址
        //*(*(a+i)+j)将对应的一维数组的元素数据取出
        for (j = 0; j < 3; j++)
        {
            cout << "a[" << i << "]" << "[" << j << "]数据:" << *(*(a+i)+j) << endl;
        }
    }
    cout << endl;

    //指针访问二维数组-2
    cout << "指针访问二维数组-2" << endl;
    for (p = a,i = 0; p < a+2; p++,i++)
    {
        for (j = 0; j < 3; j++)
        {
            cout << "a[" << i << "]" << "[" << j << "]数据:" << *(*p+j) << endl;
        }
    }
    cout << endl;
}

将TwodimensionalArray函数放在main函数中运行,结果为:
二维数组
在使用指针访问数组方式2中,如果定义的指针是int *p,是不能将p=a,因为在这里p关联的是int类型的数据,而a关联的是一个长度为3的一维整形数组。所以此处定义了一个与a关联相同类型的指针变量,将a赋给p之后,可以对p进行p++操作,因为p是一个变量。

总结:还是觉得这句话讲得精辟:数组结构是递归的,n维数组的每一个元素都是n-1维数组。

数组作为参数

数组名作为函数参数

数组名作为函数参数时,c++做传地址处理。调用函数时,形参数组名接受实参数组地址,函数通过形参指针对实参数组间接访问。

/**********************************************************
* 函数:PrintArray
* 描述:输出数组元素
* 参数:int x[] - 形参数数组名
        int length - 数组长度 
* 返回:无
* 备注:
**********************************************************/
void PrintArray(int x[], int length)
{
    int i;
    cout << "数组的元素为:" << endl;
    for (i = 0; i < length; i++)
    {
        cout << x[i] << " ";
    }
    cout << endl;
}
int a[] = {1,3,4,5,6,75,4,3};
int main()
{
	PrintArray(a,sizeof(a)/ sizeof(int));
 }

PrintArray函数的参数int x[]为形参数数组名,a将其地址传给形参,在函数内可以通过形参访问数组a的元素。

参考资料:C++程序设计基础(周霭如 林伟健)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值