【学习笔记】数组与指针

这篇博客详细介绍了C++中的数组和指针概念,包括一维和二维数组的定义、存储结构、初始化和应用,以及指针的定义、内存地址、间接访问、指针变量、空指针、指针运算、指针作为函数参数等功能。此外,还讨论了指针与数组的关系,如指向数组元素的指针和二维数组的表示方法,以及字符串的表示、处理函数和指针数组与多级指针的概念。
摘要由CSDN通过智能技术生成

数组与指针

目录

  1. 数组及其应用
  2. 指针及其应用
  3. 指针与数组
  4. 字符串
  5. 指针数组与多级指针
  6. 引用

前言
数组和指针是C++的一个核心内容,也是其比较难以理解的一部分。接下来我会把它们都梳理一遍,这样我们可以更好地理解。

1. 数组及其应用

数组的概念:具有相同类型的一批数据所构成的整体称为数组。数组的名字简称为数组名,数组中的数据称为数组元素

一维数组
数组的四个要素:名字、类型、大小和维数。
一维数组的定义形式:
类型符 数组名[常量表达式];
常量表达式必须是整形,表示的是数组的元素的个数,即数组的长度或大小。类型符指定数组的类型。

一维数组的引用
引用形式: 数组名[下标]
一维数组的存储结构
程序运行期间,每一个变量对应特定的储存单元,一维数组的内存则占据一片连续的储存单元,数组元素按下标从小到大连续排列,每个元素占用相同的字节数。
一维数组的初始化
(1) 顺序列出数组的全部元素的初值
例如:int a[3]={0,1,2};
(2) 仅对数组的前面一部分设立初始值
这样不会报错,后面没有设里初始值的元素为空(null)
(3) 对全部数组元素设立初值,可先不指定数组元素的个数。
例如:
int a[]={0,1,2,3,4};
编译系统会根据括号中的数据的个数来确定数组的元素个数。
例题
从键盘输入N个数按从小到大的顺序输出。
代码示例

#include <iostream>
#include <iomanip>
using namespace std;
//定义N,后面不要加;
#define N 10
//主函数
void main()
{  
    int x[N];
    cout << "Please input N integer:" << endl;
    for(int i = 0; i<N; i++){
       cin>>x[i];
    }
    //冒泡排序
    for (int i = 0; i < N;i++) {
        for (int j = i; j < N;j++) {
            if (x[i]>x[j]) {
                int temp = x[i];
                x[i] = x[j];
                x[j] = temp;
            }
        }
    }
    //输出
    cout << "The sorted numbers:" << '\n';
    for (int i = 0; i < N;i++) {
        cout << setw(6) << x[i];
        } 
    }

二维数组
二维数组的定义形式
类型符 数组名 [常量表达式1][常量表达式2]
例如:int x[3][4];
同理三维数组的定义方式:
例如:int x[3][4][5];
二维数组的储存结构
在这里插入图片描述
程序运行时,二维数组占据一片连续的内存单元。在内存中二维数组是按行的顺序存放的。
二维数组的初始化
(1)按行给二维数组设定初值
例如:
int y[2][3]={{1,2,3},{4,5,6}}
(2)按元素排列顺序初始化
例如:
int y[2][3]={1,2,3,4,5,6}
但是这样结构性差。
(3)对部分元素设立初值
例如:
在这里插入图片描述
类似于矩阵的创建。
(4)如果对数组的全部元素赋初值,定义数组时,第一维的大小可以不指定
例如:
int y[][3]={1,2,3,4,5,6};
编译系统会根据给出的初始数组个数和其他维的元素个数确定第一维的大小。
例题
在这里插入图片描述
代码示例

#include <iostream>
#include <iomanip>
using namespace std;
//定义MN,后面不要加;
#define M 3
#define N 4
//主函数
void main()
{ 
    //定义数组
    int a[M][N];
    cout << "Please input N*M number:" << endl;
    for (int i=0; i<M;i++) {
        for (int j = 0; j < N;j++) {
            cin >> a[i][j];
        }
    }
    //输出最大元素和下标
    int max, column=0, row=0;
    max = a[0][0];
    for (int i = 0; i < M;i++) {
        for (int j = 0; j < N;j++) {
            if (max<a[i][j]) {
                max = a[i][j];
                row = i;
                column = j;
            }
        }
    }
    //输出
    cout << "\nmax=" << max << ",row=" << row << ",column=" << column << '\n';
  }

结果:
在这里插入图片描述

2. 指针及其应用

指针的概念
指针是C++的一种的重要的数据类型,其用途广泛。借助指针,用户可以用灵活多变的方式访问内存中的变量、数组、字符串、类对象和调用函数。利用指针作为函数的参数,使得被调函数可以间接的访问主调函数中的变量。用指针可以构造变量之间的指向关系,从而构造复杂的数据结构。

内存地址:内存是以字节为单位的一片连续的储存空间,为了便于访问,计算机系统给每一字节单元一个唯一的编号,编号从0开始,第一个字节单元编号0,以后个单元按顺序编号,这些编号称为内存单元的地址,利用地址来标识内存单元,就想用房间号来标识各个房间一样。地址的具体编号方式与计算机的体系结构有关。对于C++程序中定义的变量,编译系统会根据变量的数据类型为其分配相应数目的字节储存单元。

系统给某变量的分配的储存空间的首字节地址称为该变量的地址。地址就像储存单元的指示标,在高级语言形象的称其为指针,也可以说指针就是地址。
直接存取
在C++源程序中,变量名标识变量占据的储存空间和其中存储的数据,C++编译系统会将变量名转换成变量地址变量占用的储存空间由其类型决定机器指令对变量或者内存单元的访问则使用其地址。这种变量名或者地址存取变量值的方式称为变量的直接存取方式。

间接存取
在这里插入图片描述
如图,系统为p分配的地址为4000,为a分配的地址为2000,我们可以先通过变量名p取得p的值2000,即a的地址来访问a的值123。

指针变量:这时我们可以称变量p为一个指针变量。指针变量是用来存放地址(指针),通过指针变量可以访问它所指向的变量,通过这种“指向关系”可以建立变量之间的逻辑联系。
指针变量的定义及初始化
指针变量定义的一般格式
数据类型 *变量名;
其中,符号标识定义指针变量,类型标识该指针能指向的对象的类型,也成为指针表变量的基类型。

int a,*p=&a;
该定义表示设置指针变量的初值为a的地址,说明指针指针p指向a,&为取地址运算符。
*p=123;和a=123是等效的。两者都指向a变量。
空指针
如果一个指针变量没有指向任何对象,我们称其为空指针,我们在设置指针变量时可以将其初始化为NULL或0。如果未指定初值,系统会自动给它指定初值0。

指针的运算
间接访问运算
*指针
运算符 * 和&都是单目运算符且具有相同的优先级。
a与*(&a)是等价的。
指针变量的赋值
程序运行时,可用赋值运算修改指针变量的值。可以将一个变量的地址赋值给指针表变量,也可以将一个指针变量赋值给另一个指针变量。
指针的加减运算
指针可以与整数进行加、减运算的出新的地址值。在对指针进行加减整数n时,其结果不是直接加减n一般是加减"nXsizeof(指针基类型)"。在Viual C++编译系统中,基类型为字符型的指针加1,其结果加1;基类型为整型的指针,其结果加4(整数占4个字节),其他的以此类推。

相同类型的两个指针可以相减,结果是两个指针的(地址)值相隔的存储的空间的个数,一个村出口评鉴一般包括sizeof(指针基类型)的字节数。
注意
小值指针减大值指针的结果为复数。两个指针不能相加,不管其类型是否相同。

指针做函数参数
指针变量可以作函数的形参,对实参地址或指针变量。所以实参和形参的地址是一样的,所以函数可以改变实参指针指向变量的值。

例如下面的指针交换两数的指向地址实现数的交换:

#include <iostream>
using namespace std;
//交换两数的值(运用指针)
//定义交换函数
void swap(int *p1,int *p2) {
    int temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}
//主函数
void main()
{ 
    int a, b;
    cout << "please input two integer number:" << endl;
    cin >> a >> b;
    swap(&a, &b);
    cout << "a=" << a << '\t' << "b=" << b<<endl;
  }

结果
在这里插入图片描述
返回指针值的函数
函数的返回值可以是指针类型的数据,即地址。返回指针值的函数也称为指针函数。
定义指针函数的一般形式:
数据类型 *函数名(形式参数表)
注意
指针函数返回值不能是本函数中局部变量的地址,因为本函数执行完毕返回主调函数后,函数中的局部变量全部释放,主调函数再去访问,不能保证结果的正确性。返回值可是主调函数中局部变量的地址、数组元素的地址或者全局变量的地址等。

指向函数的指针
程序运行时,一个函数包括的指令序列占据一段内存空间,这段内存空间的首字节编号称为函数的入口地址,编译系统用函数名代表这一地址。所以函数的入口地址称为函数的指针,简称函数指针。

用函数名调用函数称为函数的直接调用,用函数指针变量调用函数称为函数的间接调用。
函数指针变量的定义
一般格式:
数据类型 (*变量名)(形参类型表)
如:int (*p1)(int,double);
注意: 第一个括号不能少,不然就变成定义返回指针类型的函数。
用函数指针调用函数
1.定义了函数的指针变量,可以给它赋值对应函数的地址。函数名代表函数的入口地址,所以:
函数指针变量=函数名;
2.调用函数:
当一个函数指针变量指向某一个函数时,就可以调用它:
函数指针变量(实参表)
或(*函数指针变量)(实参表)
代码示例
下面是求圆周长和面积的程序:

#include <iostream>
using namespace std;
#define PI 3.1415926
//声明函数
float area(float), perimeter(float);
float fun(float,float(*)(float));//形参含有函数指针
//主函数
void main()
{ 
    float r, s, l;
    float(*q)(float);
    cout << "please input r:" << endl;
    cin >> r;
    s = fun(r, area);
    q = perimeter;
    l = fun(r, q);
    cout << "面积为:" << s << "周长为:" << l;;
  }
//定义求面积的函数
float area(float r) {
    return (PI * r * r);
}
//定义求周长的函数
float perimeter(float r) {
    return (2 * PI * r);
}
//定义形参含有函数指针的函数
float fun(float r,float (*p)(float)) {
    float y;
    y = p(r);
    return y;
}

结果
在这里插入图片描述

3. 指针与数组

指针与一维数组
1.指向数组元素的指针变量
当指针变量的基类型与数组的数据类型一致时,将数组元素的地址或一维数组名赋值给指针变量,此时指针变量就指向数组元素。
例如:
int a[4]={1,2,3,4};
int *p=a;//等效于p=&a[0]

注意:
数组名a是常量指针或指针常量,而p是指针变量,a代表的值在程序运行过程中不能被改变,但是p的值是可以改变的,当给p赋予不同元素的值,它就可以指向不同元素,p++,可以使其指向数组的下一个元素。
一维数组元素指针表示法
在这里插入图片描述
数组名和指针变量,实参可用数组名或指针。在类型对应关系上,共有四种对应关系:即形参用数组名,对应实参可用数组名或指针,同理:形参用指针变量也可以用数组名或指针。
注意
1.* p++等价于*(p+1)
2.(*p)++表示p所指的变量加1
指针与二维数组
二维数组的各种地址和数组元素的表示方法
在这里插入图片描述在这里插入图片描述
行指针变量
行指针是指向一维数组整体的指针,储存行指针的变量叫行指针变量。如:
int (*p)[4];
行指针变量p是一个指向由4个整型元素组成的一维数组,对p进行增减1运算就表示前进或后退4个整形元素。

4. 字符串

字符串是一种非数值类型数据,它是计算机加工处理的对象。C语言用字符数组和指针表示字符串,C++仍支持这种表示方法,另外,C++还可以用字符串类型string对象来表示字符串,而字符串最终也是通过数组和指针来表示的。
字符串的概念
程序运行时,字符占据一片连续的储存空间,运行时程序根据首字符所占字节的地址来找到整个字符串。同时,为了检测字符字符串的长度,C++语言规定字符串尾添加一个字符’\0’ 作为字符串结束标志。

字符串可以包括转义字符及ASCII码表中的控制字符(以转义字符出现) 。字符串中的汉字占两个字节。
字符串的存储表示法
1.字符数组表示法
字符数组用来储存字符串,其元素依次为储存串中的各字符。内存中字符串尾总附加‘\0’字符,它要占一个字节,所以长度为L的数组可以容纳长度为L-1的任何字符,否则会出现数组越界的错误。

初始化数组:
char a1[]=“we are familly”;
结尾会自动补字符串结束的标志字符’\0’。以字符的方式初始化,则要确定字符串的大小,以便让系统去自动对数组的末尾补零。

2.指针表示法
若将字符串的首字符所占字节的地址存于字符类型的指针变量中则程序可以通过该指针变量来访问字符串中的某个字符,因此,指针是字符串的一种表示方法。
例如

char *cp="I am a studuent";
//定义了指向字符的指针变量cp,用*(cp+i)或cp[i]就能访问字符串中
//的第i个字符

注意
用字符串数组和指针变量都可以表示字符串,但是两者还是有一定区别的。
1.字符数组为字符串提供储存空间,而字符指针不能。
2.数组名代表数组内存空间首地址,是常量指针。
3.数组名是常量指针,就不能一个字符串给一个字符数组赋值。
例如:

char a[30];
a="I am a student";
//上面赋值是错误的
//但是可以给一个字符串数组初始化,也可以之后给每个元素单独赋值
char a[30]="I am a student";

字符串的输入与输出
两个方式:
1.逐个字符输入输出,用循环结构控制
2.整体作为字符串一次性输入输出,以下的方式:
输出字符串在标准C输入输出(Standard C I/O)函数库中的字符串输入输出函数(scanf、printf、putcahr、getchar、gets、puts等),C++同样也支持这些函数。另一种就是用C++的标准输入输出流对象cin和cout。使用标准输入流时,为了不包含回车符,可以使用成员函数cin.getline()进行灵活控制。
字符串处理函数
为了方便使用字符串,C语言的字符串函数库提供丰富的字符串处理函数,C++仍然兼容它们。要使用它们,现在程序首部加上#include
1.字符串连接函数strcat()
例如

char s1[30]="this";
char s2[30]=" is";//有一个空字符
strcat(s1,s2);
cout<<s1;

连接的图示:
在这里插入图片描述
注意:返回的数组为第一个数组s1,新的数组s1有效字符串之后会保留一个‘\0’,之前的‘\0’被覆盖了,所以先前的数组剩余的空间必须大于要链接的数组的长度,否则会报错。
2.字符串拷贝函数strcpy()和strncpy()
调用格式:strcpy(s1,s2);
功能:将后面的数组复制到第一个数组。
3.字符串比较函数strcmp()
在这里插入图片描述
4.子串查找函数strstr()
函数调用该函数,在str1中是否有包含字串str2,若有则返回第一次出现str2的位置的地址,否则返回NULL。
5.字符串大写字母转为小写字母struwr(),小写转化成大写strupr()
6.求字符串长度的函数strlen()
返回字符串的长度,不包括‘\0’

5. 指针数组与多级指针

指针数组
如果一个数组的元素是指针类型的数据,则该数组称为指针数组。一维指针数组定义格式为:
类型符 数组名[常量表达式]
注意:
指针数组和普通数组的区别就是,数组中的每一个元素都是指向类型符变量的指针。数组名代表第一个元素的地址。同时
和数组名外不要加括号,否则变成了行指针变量。
功能:
用指针数组表示一批指针数据。
多级指针
指针变量的地址仍是指针,叫多级指针。存放其他指针变量地址的变量叫多级指针变量,也简称多级指针。
例如:

int a=22;
int *p=&a;
int **pp=&p;
//a可以用*p和**pp表示

同理:
可以定义多级指针
如三级指针:int ***p;
带形参的main函数
带形参的main()函数的一般形式:
int main(int argc,char *argv[])
示例
编写程序,要求输出运行该程序时所输入的命令行参数。

#include <iostream>
using namespace std;
//主函数
void main(int argc,int *argv[])
{ 
    int k;
    cout << "argc=" << argc << endl;
    for (k = 0; k < argc;k++) {
        cout << "argv" << k << ":" << argv[k] << '\n';
        cout << '\n';
    }
  }
6. 引用

程序可以用变量名来直接访问变量,也可以用指针变量间接访问变量,另外,C++中,程序还可以引用(reference)来访问变量。用引用作函数参数和返回值可以扩充函数传递参数的能力。
变量的引用:

int a;
int &ar=a;
//为变量a定义了一个引用ar,ar也表示a的储存单元,此处&是引用声明符,
//不是取地址运算符

总体来说,引用跟指针变量有相似之处,利用引用作为函数的参数也可以达到改变实参的目的,并且代码更加的简洁。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值