导图社区 数组与指针
这是一篇关于数组与指针的思维导图,知识点有数组的定义及元素引用、数组的初始化、指针变量的标明和使用、指针的运算等。
编辑于2022-04-03 15:57:07数组与指针
数组 1、定义:数组是类型相同、数目固定的若干个变量的有序集合 2、数组中的每个变量称为数组元素。数组中的每个元素对应存储器的一个存储空间,元素的值就存放在这个空间,并用下标标识数组中每个元素的位置。 3、分类:一维数组、二维数组等
数组的定义及元素引用 1、数组是由相同数据类型的元素按一定规则组合而成的,是一组具有相同名字而下标不同的变量 2、数组名由用户定义,使用前需要先声明。定义数组与定义变量一样,用类型名定义
一维数组的定义及元素引用
一维数组的定义
定义数组包括定义类型、名字、维数及数组中元素的个数
定义形式:类型名 数组名【常量表达式】 其中常量表达式的值为数组中元素的个数
定义数组后编译系统就为其分配一块连续的存储单元。所谓连续的区域是指相邻两元素之间没有空间
注意:定义数组时【】中必须是整型常量表达式,不能是变量。
元素引用
定义数组后才能在程序中使用,在程序中使用的是数组的元素
引用形式:数组名【下标】
C++规定数组元素下标的取值由0开始,最后一个元素的下标是数组定义中常量表达式的值减1
数组的下标是整形表达式。在程序中一般使用一个变量控制数组元素的下标依靠下标变量的变化表示不同的数组元素。如: int a[5]; for(int i=0;i<5;i++) a[i]=2*i;
二维数组的定义及元素引用
定义形式:类型名 数组名【常量表达式1】【常量表达式2】 如:int x[3][4];[3]为第一维,[4]为第二维,可以将其视为矩阵
行和列下标元素的取值也是由0开始的
二维数组元素的引用形式:数组名【行下标】【列下标】
二维数组在计算机内是按行号升序,行内按列号升序存放的,一般常用两个变量控制二维数组元素的行下标和列下标。如 double data[5][4]; for(int i=0;i<5;i++) for(int j=0;j<4;j++) data[i][j]=(i+j)*0.5;
数组的初始化——将数组赋予初值
一维数组的初始化
形式:int a[5]={5,10,15,25,30};
一维数组初始化时,数组名后【】中的常量可以省略,编译系统自动计算数组的大小
给数值型数组赋初值时,若所赋常量的个数少于定义数组元素的个数时,没有赋值的元素值按0来处理;反之,若所附初值多于定义数组元素的个数时,则产生编译错误
二位数组的初始化
可以有以下几种形式: int b[2][3]={{1,3,5},{2,4,6}} int b[2][3]={1,3,5,2,4,6}系统先取前3个数作为第0行,再取后三个数为第一行 int x[3][3]={{1},{2,3}{4,5,6}} int x[3][3]={1,2,3,4,5,6,7}不足的补0 int x[][4]={1,2,3,4,5,6,7,8,9,10,11,12}
定义中最左边[]中的常量值可以省略,编译系统根据初始化的值的个数自动计算,但表示列[]中的常量不可以省略
字符型数组的初始化
既可以赋字符常量,也可以赋字符串
给字符型数组赋字符串时,每个数组元素存放一个字符,字符串的长度即为字符型数组中元素的个数。给字符型数组赋字符串时定义的长度要比实际字符个数多1,以存放字符串结束标志‘\0’
子主题
子主题
以下几种初始化形式是等效的: char ch[6]={'t','o','t','a','l','\0'}; char ch[6]="total"; char ch[]={"total"}; char ch[]="total";
一般一维字符型数组赋初值时常省略[]中表示数组大小的常量
字符型数组赋单个字符时,存放的是字符而不是字符串。如: char d[]={'\t','\t','\a','\a','\n'};这种方式通常用于在键盘上生成不可见字符
注意数组元素的个数与所赋字符串长度的关系,以免引起错误。当数组定义的空间大于初始化字符串长度时,剩余的空间填充‘\0’
二维字符型数组初始化
数组的输入输出
C++中一般将字符串存储在字符数组中,因此字符数组的输入输出可以有两种方法,即逐个字符输入输出和将整个字符串输入输出。 逐个字符输入输出与数值型数组的输入输出相同,即用一变量控制数组的下标,根据下标的变化输入或输出单个字符。将整个字符串输入输出时,在cin和cout中只用数组名即可
字符串输入输出要注意的点
用cin和cout输入输出字符串时,只写数组名
用cin输入字符串时,当输入空格、制表符或回车时,输入结束,系统在最后自动加一‘\0’字符。例如: char str[10]; cin>>str; 执行时,若从键盘输入:I love C++<回车> str数组的内容是:“I\0”两个字符,输入的其他字符没有送到strs数组。因此用cin输入字符串时要注意中间不能有空格或制表符。若输入含有空格或制表符的字符串时,可以用字符串输入函数gets()或输入流的成员函数get()、getline()
用cin输入字符串时,输入字符的个数要小于字符数组定义时的长度
用cout输出字符串时,遇到第一个'\0'输出结束,'\0'不输出。一般形式为: cout<<字符型数组名; 他表示以字符串形式输出数组中的全部内容。此形式仅用于字符型数组,其它类型的数组不能用数组名作为输出,只能用数组元素。
数组的应用
冒泡法
指针 指针变量中存放的不是数据,而是内存单元的地址,通过这个地址可以访问其中的内容。 定义:存放变量地址的内存单元称为指针变量,简称指针
指针变量的声明和使用
指针变量的声明
形式:类型名 *标识符;
指针变量前的*为声明指针变量的说明符,而不是指针变量的一部分,只是说明后面的标识符是指针变量名,而不是普通变量名。指针的类型就是他所保存的地址中所存储的数据的类型
指针变量的使用
& 取变量地址运算符 * 取指针变量所指对象内容的运算符
数组名是个地址常量,而指针是个地址变量。编译时数组名作为数组的首地址以确定,程序运行时其值时固定不变的。因此,若定义 int a[10]; 后进行a++或a=p等运算都是错误的。而指针是个地址变量,将哪个数组名赋给它,它即指向哪个数组。
其中&仅对一般变量使用,表示取该变量的地址。*放在指针变量名前,表示取指针变量所指单元的内容
如: int a,*p1; p1=&a; //将变量a的地址赋给指针p1 *p1=25; //将25赋给指针p1所指的单元中
注意,语句中*p1=25中的“*”和声明指针变量前的“*”不同。程序中出现在指针变量名前的“*”是运算符,表示取指针所指内容。而声明时出现的“*”仅表示“*”后的某标识符定义为指针变量名
指针变量的赋值
指针变量声明后,在使用前必须给他赋一个合法的值。既可以在程序中赋值,又可以在声明时对指针进行初始化
如: int x=50; int *px=&x; double *py=0;
px指向整型变量x。 在声明py指针时初始化为0,值为0的指针叫空指针。空指针表示不指向任何地方
注意事项
对指针赋的值必须是同一种类型变量的地址
指针也是个变量,程序中将哪个变量的地址赋给指针,指针就指向哪个变量。指针只能接受地址量,不能将任意常数赋予指针,除0以外!!!同类型的指针之间可以互相赋值
指针不能悬空使用,如: int *p; *p=200;这个写法是错误的
指针的运算
取变量地址:&a
取指针所指内容:*p
*p可以用a代替
指针间赋值:p=q
指针增1或减1:p++,p--或++p,--p
指针加上或减去一个整数n:p+n或p-n
指针相减:p-q
指针关系运算:p<=q
这些运算只有与数组结合起来使用才有实际意义
指针加或减1运算是指针由当前位置向前或向后移动一个数据单元。n就是n个
当两个指针指向同一数组的不同元素时,指针相减的结果即是两指针所指位置间的数据的个数
两个指向同一数组的指针进行关系运算时,表示的是他们所指单元的先后位置
指针与数组 任何由数组下标完成的操作都可以用指针实现
一维数组与指针
数组名作为该数组的首地址使用
如:int array[5]={1,2,3,4,5}; array和&array[0]是相等的,所以array+i和&array[i]是相等的 *array表示的是元素array[0]的值,*(array+i)表示的是第i个元素的值
程序中,可以用array[i]表示数组中的第i个元素,也可以用*(array+i)表示第i个元素 第i个元素的地址既可以用&array[i]表示,也可以用array+i表示
数组名访问数组元素与用数组下标的结果相同
可以声明一个与数组类型相同的指针,然后让这个指针指向数组,通过这个指针访问这个数组
如:int a[10],*p; p=a; 此语句把数组a的首地址给指针p,p即为指向数组a的指针。因此p+1指向a[1],p+i指向a[i]
总结:表示一维数组a中的第i个元素的地址可以用以下几种形式 &a[i] a+i p+i 表示一维数组a中的第i个元素,可以用以下几种形式 a[i] *(a+i) *(p+i)
用指针处理数组时需要注意的点
当指针运算符与其他运算符联合使用时,要注意运算符的优先级别
*p++ //取p所指内容后,p加1 *++p //p指针加1后,所指的内容 (*p)++ //将所指向的单元内容加1
用指针处理数组时,指针移动的值不要超过数组元素下标定义的范围
多维数组与指针
int a[3][[4]; a数组是由三个元素组成的一维数组,这三个元素的名字为a[0],a[1],a[2],其中的每个元素又是由四个元素组成的一维数组
数组名是指向数组的首地址。因此a是三个一维数组a[0],a[1],a[2]的首地址。而a[0],a[1],a[2]又是三个数组名,分别表示三个一维数组的首地址
表示二维数组第i行第j列元素的值可以有以下几种形式 *(*(a+i)+j) *(a[i]+j) a[i][j]
字符型指针与字符型数组
将一个字符串赋给一个字符型指针时,该指针指向字符串的首地址,即第一个字符的地址
字符型数组和字符型指针的区别
字符型数组只能在初始化时为整体赋值,不能在程序中向数组名赋值。而字符型指针除初始化外,还可以在程序中赋字符串
如: char s[10],*p; s="abcdefg"; //出错,s为地址常量,不能出现在=左侧 p="abcdexy"; //正确,p为字符型指针变量,可以出现在=左侧
对于字符型数组,编译程序根据定义时数组的大小分配存储空间。而对于字符型指针,仅给该指针变量分配存放一个地址的单元。该单元可以存放任一字符串的首地址
堆内存分配 程序运行时的数据空间通常是在程序设计时通过定义变量或数组的方式由系统预先分配。但在设计程序时,有些数据空间的大小还不能确定,只有在程序运行过程中才能确定,使用堆内存可以实现这一功能。
含义:堆是一种内存空间,它允许程序运行时根据需要申请内存空间。由于这种空间的大小在编译和连接时不确定,而是随着程序运行可大可小,所以堆内存是动态的,又称动态内存分配
new(用于申请一块动态内存空间)
使用形式: 指针=new 数据类型名
作用:从内存的动态区域申请指定数据类型所需的存储单元。若分配成功,该存储单元的首地址赋给指针;否则,指针得到一个空地址。其中指针所指的数据类型要和new后边给定的数据类型相同
如: double *p; p=new double;
初始化 double *p; p=new double(12.3576)
另一种使用形式:指针=new 数据类型【元素个数】 指针=数据类型【行数】【列数】
这是动态创建一维数组,其中元素个数可以是个变量!!! 注意:动态地为数组分配内存空间时不能对数组进行初始化
delete(对new创建的存储单元进行释放)
使用形式: delete 指针名; //释放指针所指内存单元 delte[]指针名; //释放数组的内存单元
需要说明的点
delete并不删除指针,必要时可以对指针重新赋值。如: int *pi=new int(5); delete pi; pi=new int;
对于指向动态分配内存单元的指针,在其所指向的内存单元没有释放前,该指针不能重新赋值。如: int *pi=new int; *pi=5; pi=new int; //出错
对每个new运算符创建的内存单元,只能用delete释放一次不可连续多次释放 int *p; p=new int; delete p;delete p; //第二次释放将产生运行错误
但delete可以对内容为空的指针进行多次连续释放。如: int *p=NULL; delete p;delete p;//安全