最近有人问到我:“为什么我的代码能在OJ上AC,但是在本地编译器中编译后连输入的机会都没有。”这种情况往往和数组的声明方式有很大的关系。
C语言中,内存主要被分为5大板块,而全局变量存储在全局(静态)区,局部变量存储在栈区。而静态区是在程序运行之初就分配好的内存空间,内存的大小在程序的运行过程当中是不会发生改变的。而与之对应的堆内存则存储在堆区,堆在c语言程序的运行过程中是由低地址向高地址增长的,在增长的过程中有机会和由高地址向低地址增长的栈区发生冲突,从而引发内存泄漏。
啊啊,你究竟在说些什么(bushi
在这里我将会用通俗易懂的语言介绍一下全局的数组和局部的数组的区别
全局数组:
作用范围(全局)
是否会自动初始化(会)
可以开多大的(1e8甚至更大)
局部数组:
作用范围(函数内或循环内)
是否会自动初始化(不会) 使用memset(a,0,sizeof a)初始化即可,注意第二个值是对内存的操作,如果将0修改为0x3f,则a中的每一项数据均会被初始化成0x3f3f3f3f)
可以开多大的(1e4以内,但一般超过1e4就不建议了)
下面来举个例子:以下是某位同学的高精度加法的代码,在AcWing的OJ中可以AC,但是在本地编译器(Dev C++ 17)中是无法运行的(可以编译但是没有机会输入)
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int main()
{
char a[N],b[N];
int A[N],B[N];
scanf("%s %s",a,b);
for(int i=strlen(a)-1,j=0;i>=0;i--,j++) A[j]=a[i]-'0';
for(int i=strlen(b)-1,j=0;i>=0;i--,j++) B[j]=b[i]-'0';
int lena=strlen(a),lenb=strlen(b);
int C[N];
int t,i;
for( i=0;i<lena||i<lenb;i++)
{
if(i<lena)t+=A[i];
if(i<lenb)t+=B[i];
C[i]=t%10;
t/=10;
}
if(t!=0){
C[i]=t;
for(int j=i;j>=0;j--)printf("%d",C[j]);
}
else for(int j=i-1;j>=0;j--)printf("%d",C[j]);
return 0;
}
这种情况出现的原因是堆内存出现了内存泄漏,在main函数内部定义了3个局部的数组A,B,C,三个数组的大小均为1e6,超出了堆内存的上限,因此,只需要把A,B,C三个数组的定义移动到main函数外面即可。
另外这段代码还有另一个问题,就是堆内存变量在定义的过程当中,不一定会被自动初始化为0,而代码中的变量t是在main函数中定义的,因此变量t需要被初始化。但是如果这位同学将t的定义移动到main函数外面,形成一个全局变量,就不存在这个问题。