对于一维数组想必大家都很熟悉了,就不做太多的阐述了。
指针的数组表示
在C++内部,用指针来处理数组
C++编译器把数组名[下标]
解释为*(数组首地址+下标)
C++编译器把地址[下标]
解释为*(地址+下标)
对于数组名[5]
,其实数组名
就是该数组的首地址,例如a[5]
,这个a
就是数组
的首地址,用*p=a
之后我们就可以用*(p+i)
来访问数组第i个值。
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int a[5]={3,6,5,8,9};
for(int i=0;i<5;i++){
cout<<"a["<<i<<"]的值是:"<<a[i]<<endl;
}
int *p=a;
for(int i=0;i<5;i++){
cout<<"*(p+"<<i<<")的值是:"<<*(p+i)<<endl;//把`数组名[下标]`解释为`*(数组首地址+下标)`
cout<<"p["<<i<<"]的值是:"<<p[i]<<endl;//把`地址[下标]`解释为`*(地址+下标)`
}
}
一 维指针用于函数的参数
一维数组用于函数的参数时,只能传数组的地址,并且必须把数组长度也传进去,除非数组中有最后一个元素的标志。
书写方法有两种:
void func(int *arr,int len)
void func(int arr[],int len)
注意:
在函数中,可以用数组表示法,也可以用指针表示法。
在函数中,不要对指针名用sizeof运算符,它不是数组名。(在函数中我们使用sizeof(arr))它是的等于一个定值8的,因为我们使用数组做形式参数的时候他会退化成一个指针,而一个指针大小就是8)
#include<iostream>
#include<algorithm>
using namespace std;
void func(int *a,int len){
for(int i=0;i<len;i++){
cout<<a[i]<<endl;
}
}
void func1(int a[],int len){
for(int i=0;i<len;i++){
cout<<a[i]<<endl;
}
}
int main(){
int a[5]={3,6,5,8,9};
func(a,sizeof(a)/sizeof(int));
func1(a,sizeof(a)/sizeof(int));
}
用new动态创建一维数组
普通数组在栈上分配内存,栈很小,如果需要存放更多的元素,必须在堆上分配内存。
动态创建一维数组的语法:数据类型 *指针=new 数据类型[数组长度]
,释放一维数组的语法delete[] 指针
。
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int *a=new int[8];
for(int i=0;i<8;i++){
a[i]=100+i;
cout<<"arr["<<i<<"]"<<*(a+i)<<endl;
}
delete[] a;
}
注意
● 动态创建的数组没有数组名,不能用sizeof运算符。
● 可以用数组表示法和指针表示法两种方式使用动态创建的数组。
● 必须使用delete[]
来释放动态数组的内存(不能只用delete)。
● 不要用delete[]
来释放不是new[]
分配的内存。
● 不要用delete[]
释放同一个内存块两次(否则等同于操作野指针)。
● 对空指针用delete[]
是安全的(释放内存后,应该把指针置空nullptr)。
● 声明普通数组的时候,数组长度可以用变量,相当于在栈上动态创建数组,并且不需要释放。
● 如果内存不足,调用new
会产生异常,导致程序中止;如果在new
关键字后面加(std:nothrow)
选项,则返回nullptr
,不会产生异常。
● 为什么用delete[]
释放数组的时候,不需要指定数组的大小?因为系统会自动跟踪已分配的内存。
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int *a=new(std::nothrow) int[100000000000];
if(a==nullptr){
cout<<"分配内存失败\n";
}
else{
a[10000]=8;
delete[] a;
}
}
二维数组用于函数的参数
int* p;//整型指针。
int* p[3];//一维整型指针数组,元素是3个整型指针(p[0]、p[1]、p[2])。
int* p();//函数p的返回值类型是整型的地址。
int (*p)(int ,int);//p是函数指针,函数的返回值是整型。
行指针(数组指针)
声明行指针的语法:
数据类型(*行指针名)[行的大小];
//行的大小即数组长度。
int (*p1)[3];
//p1是行指针,用于指向数组长度为3的int型数组。
int(*p2)[5];
// p2行指针,用于指向数组长度为5的int型数组。
double (*p3)[5]
;//p2是行指针,用于指向数组长度为5的double型数组。
一维数组名被解释为数组第0个元素的地址。
对一维数组名取地址得到的是数组的地址,是行地址。
二维数组名是行指针
int bh[2][3]={{11,12,13},{21,22,23}}
bh是二维数组名,该数组有2两元素,每一个元素本身又是一个数组长度为3的整型数组。
bh 被解释为数组长度为3的整型数组类型的行地址。
如果存放bh
的值,要用数组长度为3的整型数组类型的行指针。
int (*p)[3]=bh;
把二维数组传递给函数
void func(int (*p)[3],int len);
void func(int p[][3],int len);
#include<iostream>
#include<algorithm>
using namespace std;
void func(int p[][3],int len){
for(int i=0;i<len;i++){
for(int j=0;j<3;j++){
cout<<p[i][j]<<" ";
}
cout<<endl;
}
}
int main(){
int bh[2][3]={{11,12,13},{21,22,23}};
int (*p)[3]=bh;//可以
func(bh,2);
//int *p1=bh;//不行
}