对 数组越界 和 地址分配 的 思考 和 测试 (提升理解)

简介: 对 数组越界 和 地址分配 的 思考 和 测试 (提升理解)

前言:


今天敲了个埃式筛的求素数的程序,求1000以内素数的个数,犯了低级的数组越界的错误,在这里做个小记录,非常有意思;


给出代码:


#include<bits/stdc++.h>
using namespace std;
const int N = 1e4;
int prime[N];
int cnt,cnts;
void Isprime()
{
  prime[0]=1;
  prime[1]=1;
  for(int i=2;i<=N;i++)
  {
  if(prime[i]==0)
  {
    for(int j=i*2;j<=N;j+=i)
    {
    prime[j]=1;
    }
  }
  }
  for(int i=1;i<=N;i++)
  {
  if(prime[i]==0)
  {
    prime[++cnt]=i;
  }
  }
}
int main()
{
  Isprime();
  for(int i=1;i<=1000;i++)
  {
  if(prime[i]<1000) cnts++;
  }
  cout<<cnts;
}


很经典的一个埃式筛求素数的程序(用了同一个数组做了内存优化),求前一千个数中素数的个数,答案应该是 168个,但是我的程序错误的求出了169个,于是我寻根溯源,不断地进行测试,发现cnt的初始值在函数中埃式筛的核心代码段被改变了,cnt是从 1开始的,而非0;


测试代码:


void Isprime()
{
  prime[0]=1;
  prime[1]=1;
  cout<<cnt<<endl;
  for(int i=2;i<=N;i++)
  {
  if(prime[i]==0)
  {
    for(int j=i*2;j<=N;j+=i)
    {
    prime[j]=1;
    }
  }
  }
  cout<<cnt<<endl;
  for(int i=1;i<=N;i++)
  {
  if(prime[i]==0)
  {
    prime[++cnt]=i;
  }
  }
}


测试输出:


0
1
169


当时我真是觉得离了天下之大谱了,我没有在埃式筛中改变计数器的值,但它自己好像有什么灵性一样自己改变了,我又看了好久并询问了学长学姐,终于找到了原因,罪魁祸首就是数组越界;


素数数组的大小是 N 下标就是 0 ~ N -1 但是我错误的让埃式筛的代码跑到了 N 的 位置,恰好定义的时候先定义的素数数组后定义的cnt计数器,导致 通过prime[N]错误的访问到了cnt的地址 这时恰好 N=1e4不是一个素数,被赋值成 1 ,计数器下标从 1 开始,我使用的又是++cnt计数器从二开始计数,所以多出的一个就找到了;


验证1:


为了证明我们的思想,我们可以输出prime[N-1]的地址和cnt的地址进行验证看他们是否相邻,int类型只要相差四个字节就是相邻


printf("%d\n",&prime[N-1]);
  printf("%d\n",&cnt);


果然他们是相邻的


验证2:


我们前面说 通过prime[N]错误的访问到了cnt的地址 ,我们也可以验证一下这个,给所有不是素数的值赋值一个1212,看cnt的初始值


for(int i=2;i<=N;i++)
  {
  if(prime[i]==0)
  {
    for(int j=i*2;j<=N;j+=i)
    {
    prime[j]=1212;
    }
  }
  }
  cout<<cnt<<endl;


结果:


3673c2fc205a9240fad1118de0255abe_f945dc386b564f088a3a84391e1f905c.png


结语:


当然我们也可以通过很多其他的方法进行验证,这个探索过程让我知道了数组千万不能越界,不然会带来很多乌龙,很多不可思议的错误,闹和我一样的笑话,数组千万不能越界!!!


最后给出正确的程序:(把埃式筛核心程序里的等于号都去掉即可)


**#include<bits/stdc++.h>
using namespace std;
const int N = 1e4;
int prime[N];
int cnt,cnts;
void Isprime()
{
  prime[0]=1;
  prime[1]=1;
  for(int i=2;i<N;i++)
  {
  if(prime[i]==0)
  {
    for(int j=i*2;j<N;j+=i)
    {
    prime[j]=1;
    }
  }
  }
  for(int i=1;i<N;i++)
  {
  if(prime[i]==0)
  {
    prime[++cnt]=i;
  }
  }
}
int main()
{
  Isprime();
  for(int i=1;i<=1000;i++)
  {
  if(prime[i]<1000) cnts++;
  }
  cout<<cnts;
}

以后敲代码要更加细心,加油!


目录
相关文章
|
存储 测试技术
cgroup测试存储设备IOPS分配
1 使用:创建树并且attach子系统 首先要创建文件系统的挂载点作为树的根    mkdir /cgroup/name    mkdir /cgroup/cpu_and_mem Mount这个挂载点到一个或者多个子系统     mount -t cgroup -o subsyst...
1178 0
|
Oracle 关系型数据库 数据库
ORACLE自动段管理的区分配大小测试
说明:大家知道ORACLE表空间的最小分配单元是区,当进行文件空间划分的时候每次增加的大小都是按区来进行的,且ORACLE在创建表空间的时候,关于EXTENT MANAGEMENT的管理会有两个选项:1、LOCAL AUTOALLOCATE(本地自动管理) 2、...
644 0
|
21天前
|
测试技术 C语言
网站压力测试工具Siege图文详解
网站压力测试工具Siege图文详解
27 0
|
2月前
|
JavaScript jenkins 测试技术
这10款性能测试工具,收藏起来,测试人的工具箱!
这10款性能测试工具,收藏起来,测试人的工具箱!
|
2月前
|
测试技术
现代软件测试中的自动化工具与挑战
传统软件测试面临着越来越复杂的系统架构和不断增长的测试需求,自动化测试工具应运而生。本文将探讨现代软件测试中自动化工具的应用和挑战,深入分析其优势与局限性,为软件测试领域的发展提供思路和启示。
|
2月前
|
测试技术 持续交付
现代软件测试中的自动化工具应用与挑战
随着信息技术的快速发展,软件行业对于质量和效率的要求日益提高,自动化测试工具在软件开发过程中扮演着至关重要的角色。本文将探讨现代软件测试中自动化工具的应用现状以及所面临的挑战,旨在帮助开发人员更好地理解并充分利用这一技术手段。
|
3天前
|
机器学习/深度学习 数据采集 人工智能
【专栏】利用AI辅助工具提高软件测试效率与准确性
【4月更文挑战第27天】本文探讨了AI在软件测试中的应用,如自动执行测试用例、识别缺陷和优化测试设计。AI辅助工具利用机器学习、自然语言处理和图像识别提高效率,但面临数据质量、模型解释性、维护更新及安全性挑战。未来,AI将更注重用户体验,提升透明度,并在保护隐私的同时,通过联邦学习等技术共享知识。AI在软件测试领域的前景广阔,但需解决现有挑战。
|
2月前
|
jenkins 测试技术 持续交付
现代软件测试中的自动化工具与挑战
随着软件开发领域的不断发展,自动化测试工具在测试过程中扮演着越来越重要的角色。本文将探讨现代软件测试中自动化工具的应用及面临的挑战,旨在帮助开发人员和测试人员更好地理解和应对自动化测试中的问题。

热门文章

最新文章