一.什么是数组越界
数组下标是从零开始。
比如
#include<stdio.h> int a[5] ; //合法下标只有0,1,2,3,4如果访问a[5],此时就会越界;这会导致程序逻辑混乱,崩溃,存在安全漏洞。
二.数组越界的危险性
会造成莫名其妙的bug,循环失效,数据错乱,堆栈破坏。
数组越界在某些环境下会输出乱码,另一些环境下直接崩溃。
三.常见的越界场景
1.循环下标写错
int a[5]; for(inti=0;i<=5;i++){//i<=5会走到a[5],而数组只到a[4] a[i]=0; }正确写法
int a[5]; for(inti=0;i<5;i++){ a[i]=0; } 2.使用变长数组
int n; cin>>n; cin>>a[n];//变长数组,非标准写法,易出错虽然Dev-c++n能编译,但大小不确定容易导致越界。
可以改成
vector<int>a(n)//避免越界3.二维数组的行和列容易弄错
int a[3][4]; for(int i=0;i<4;i++){ for(int j=0;j<3;j++){ //逻辑正确 } }for(int i=0;i<4;i++){ for(int j=0;j<3;j++){ //正常 } }两者都合法,但有时候会出现循环范围写错而导致越界。
4.字符串末尾容易忽略'\0'.
在C语言中
错误写法 char ch[4]="abcd";//越界,应该至少5个字节才行(含'\0') 正确写法 char ch[5]="abcd";四.如何彻底避免数组越界问题
1.永远用<长度,不要用<=长度。
2.统一用vector,避免变长数组
vector<int>a(n);优点
-安全
-不会溢出栈内存
-更标准,可移植。
3.访问数组时做合理性检查
if(idx>=0&&idx<n){ a[idx]=x; }尤其是在递归,二分中。
4.使用at()方法
在C++中
a.at(idx);a[idx]不检查
a.a(idx)会检查边界,越界直接会报错,调试的时候更容易发现错误。
四.在算法竞赛中如何避免越界
1.二分查找一定要保证left<=right的逻辑正确
错误实例 h=(left+right)/2;//可能会溢出 正确 h=left+(right+left)/2;2.使用memset时注意字节大小
memset(a,0,sizeof(a));仅对char数组安全,对Int数组要确保长度正确。
五.总结
1.数组下标永远从0开始。
2.访问必须满足0<=idx<size。
3.vector是避免数组越界的最近工具。