zoukankan      html  css  js  c++  java
  • 输入问题C++字符数组越界问题的一个案例分析

    时间紧张,先记一笔,后续优化与完善。

        我的学生yang1067155909给我来信,说的是C++第11周项目3 - CEmployee类继承自CPerson类中的一个细节:

        贺教师:

        教师,m_szDepartment=new char[strlen(department)+1];为何须要+1呢?在测试里去掉+1后和这个效果一样啊,不太明确……求指教……
    学生,杨起飞

        我回答:

        要给'\0'占个座。是用别人的土地(越界的部份)保存了自己的信息了吧,不定哪次人家要用,运行结果就不一样了。这恰是最危险的问题。

        他继续追问:

        可是在定义字符数组时,比如a[4]时,可以输入5个字符,那么这个数组的'\0'的位置是不是也占用了别人的?

        我为这个机警的同学的问题感到激昂,读程序,切忌只是读,要会提问题。能自己提出问题,就一定能学好。教师给出解答,接着再提出新问题,自己解答,或再问教师,这就是交流。为着学生提出了好问题,作为教师,我骄傲。我的回答是:

        你提的问题不是一般的好,见我新发表的博文谈这个问题。

        

        下面就是我对这个问题的解答。不妨针对问题设计一个程序试一试。程序是:

    #include <iostream> 
    using namespace std;
    int main() 
    { 
    	char a[4];
    	cin>>a;
    	cout<<a<<endl;
    	return 0; 
    }

        亲爱的读者,读这篇文章时,请不要只“读”,打开你熟习的编程环境,边读边运行。你会发现什么?

        输入abcd然后回车,输出是abcd。cout<<a是将字符数组当字符串输出的,明显abcd已经占满了自己的土地a[0]到a[3],可以“如愿”输出,实际上已经侵犯了不应占的内存a[4]单元。当然,恰好a[4]处给脸,就是'\0'。如果”烫烫烫烫烫烫“不必意外。

        每日一道理
    一个安静的夜晚,我独自一人,有些空虚,有些凄凉。坐在星空下,抬头仰望美丽天空,感觉真实却由虚幻,闪闪烁烁,似乎看来还有些跳动。美的一切总在瞬间,如同“海市蜃楼”般,也只是刹那间的一闪而过,当天空变得明亮,而这星星也早已一同退去……

        再运行,输入abcde。我运行的结果是,在VC++6.0中,输出abcde,并弹出了我们熟习的内存越界错误提示。在codeBlocks下,输出abcde,什么也没提示。

        请读者想一想,这是一个多么凶恶的Bug。

        下面再给出一个程序:

    #include <iostream> 
    using namespace std;
    int main() 
    { 
    	char a[4],b[4];
    	cin>>a;
    	cin>>b;
    	cout<<a<<endl;
    	cout<<b<<endl;
    	return 0; 
    }

        运行的任务交给读者了,视察输入3个字符、4个字符、5个字符的情形,也可以在多个平台上试试,针对结果想一想为什么。用单步执行的手腕跟踪一下内存中的数据存储,是个强烈建议的方法。

        下面是为a和b数组输入3个字符后(分别是abc和hij),利用单步执行看到的结果:

        输入和问题

        下面是为a和b数组输入5个字符后(分别是abcef和hijkl),利用单步执行看到的结果:

        输入和问题

        从中看出,VC++6.0中,先定义的a数组的地址大于后定义的数组b的地址,原来为a中输入了abcde,侵犯了别人的土地,随后为b输入hijkl,侵犯的就是a的土地,b[4]即a[0]为l,b[5]即a[1],存储的是'\0'!

        下图是在codeBlocks下,用同样的输入调试截出的结果,结果一样:

        输入和问题

        接下来,再给一个程序,其实就是将输入a和b的顺序换了一下:

    #include <iostream> 
    using namespace std;
    int main() 
    { 
    	char a[4],b[4];
    	cin>>b;
    	cin>>a;
    	cout<<a<<endl;
    	cout<<b<<endl;
    	return 0; 
    }

        运行结果会是怎样?读者你自己说吧。不要忘了,用调试工具这个法宝消除你的困惑。

        

    文章结束给大家分享下程序员的一些笑话语录: 人脑与电脑的相同点和不同点,人脑会记忆数字,电脑也会记忆数字;人脑会记忆程序,电脑也会记忆程序,但是人脑具有感知能力,这种能力电脑无法模仿,人的记忆会影响到人做任何事情,但是电脑只有程序软件。比尔还表示,人脑与电脑之间最重要的一个差别就是潜意识。对于人脑存储记忆的特别之处,比尔表示,人脑并不大,但是人脑重要的功能是联络,人脑会把同样的记忆存储在不同的地方,因此记忆读取的速度就不相同,而这种速度取决于使用的频率和知识的重要性。人脑的记忆存储能力会随着年龄增长而退化,同时记忆的质量也会随着年龄退化。经典语录网

  • 相关阅读:
    转 Nexus启动报错:Unsupported major.minor version 51.0
    eclipse中web项目发布到tomcat时项目名称不同
    转载:oracle数据库启动不了
    ajax跨域请求获取jsonp数据
    Oracle权限管理详解(转载)
    fcc jQuery 练习
    fcc 响应式框架Bootstrap 练习3
    fcc 响应式框架Bootstrap 练习2
    fcc 响应式框架Bootstrap 练习1
    fcc html5 css 练习3
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3080594.html
Copyright © 2011-2022 走看看