C++捉虫笔记
来源:互联网 发布:户型设计软件手机 编辑:程序博客网 时间:2024/04/28 07:59
《捉虫历险记—C++ bug大围剿》读书笔记
1. 你会用C++写正确Hello World 程序吗?
你认为你能吗?我写了一年多的程序,最初我认为我是可以的,但是当我看到错误的程序的时候,我却没发现那是个错误,原因只有一个,我对C++的函数的了解太肤浅了。
示例程序如下:
#include <iostream>
void main(void)
{
std::cout<<"Hello World/n";
}
你认为上面的程序是对的吗?至少我把它卸载IDE中,编译运行的时候,出现了正确的的输出结果,所以我认为是对的,其实不然。
原因:函数main()不是一个void型函数,而是一个int型函数。
正确的程序如下:
#include <iostream>
int main()
{
std::cout<<"Hello World/n";
return (0);
}
2. 静态变量和自动变量的区别
静态变量的生存期就是整个程序的运行期。在程序开始运行前就为其分配相应的存储空间,在程序的整个运行期间一直占用,直到结束。
自动变量的生存期是说明了自动变量的函数或分程序。它对存储空间的利用是动态的。其初值在每次为自动变量分配存储后都要重新设置。
示例程序:
#include <stdio.h>
//first--Demonstration of automatic variable.
int first(void)
{
int i = 0; //Demonstration variable
return (++i);
}
//second--Demonstration of static variable
int second(void)
{
static int i = 0; //Demonstration variable
return (++i);
}
int main()
{
int counter; //Call counter
for(counter=0; counter<3; counter++)
{
printf("First %d/n",first());
}
for(counter=0; counter<3; counter++)
{
printf("Second %d/n",second());
}
return (0);
}
结果输出:
3. return (++i) 和return (i++)
return (i++)
(1) 保存i的值
(2) 递增i
(3) 返回已保存的值
return (++i)
(1) 递增i
(2) 保存i的值
(3) 返回保存的值
4. 典型的初始化问题
#include <iostream>
int main()
{
int sum; //the running sum
int count; //the current number
for(count=1; count<=100; count++)
{
sum += count;
}
std::cout<<"The sum of numbers"<<"between 1 and 100 is "<<sum<<'/n';
return (0);
}
你认为上面的程序输出会是你想要的结果吗?也许吧,但机会太小了,由于初始化过程中对变量sum 没有做初始化,因此您不能指望没有初始化的变量,它可能包含任何值,所以输出结果也就可能是任何的值,正确的做法就是int sum = 0;
5. 行结束符对程序的影响
#include <iostream>
int main()
{
int result; //result of the addition
result = 2 + 2;
std::cout<<"the answer is "<<result;
std::cout<<"the answer is "<<result<<'/n'; //建议的写法
return (0);
}
作者对程序给出了这样的解释
在MS-DOS中,您会得到如下结果:
The answer is 4C:>#
(#是光标)
在UNIX系统中,您可能得到如下结果:
The answer is 4$ #
问题在程序员没有在std::cout语句的结束处加上行结束标志。结果就是:程序运行,输出一个语句,然后退出,而让光标停留在输出行的末尾位置。命令行处理器接着就继续运行,并在程序的输出内容之后输出其系统命令提示符(MS-DOS是C:>,UNIX是$)。
但我在自己机器上的执行并没有出现这样的结果,C:>始终也没有出现,我想惟一的解释就是后来的C++IDE做了改进 当你的输出结尾没有行结束符的时候自动加上。
6. 第一个内存泄露问题
这是我第一次接触到内存泄露的问题,以前只知道有这么回事,而且程序最要命的错误就是内存泄露,调试起来会很费劲,今天也算是初见端倪,看来以后真的防着这个家伙了,哈哈。
程序是这样的,输出1—5之间数字的平方仅此而已,看看下面的程序,是否满足你的要求呢?
#include <iostream>
int main()
{
int array[5]; //an array for the squares
int i; //index into the array
for(i=1; i<=5; i++)
{
array[i] = i * i;
}
for(i=1; i<=5; i++)
{
std::cout<<i<<" squared is "<<array[i]<<'/n';
}
return (0);
}
程序结果输出正确,但是会报要命的系统错误,如下图示:
其实原因很简单:
C++数值下标的基值是0。因此,数组array[5]的有效元素是:
array[0], array[1], array[2], array[3], array[4]
然而,程序员使用的元素是1-5。不存在元素array[5],因此,程序就修改了随机内存,导致内存泄漏。
这也是为什么C++程序不使用这样语句的原因:
for (i = 1; i <= 5; ++i) {
而是使用:
for (i = 0; i < 5; ++i) {
修改后的程序如下:
#include <iostream>
int main()
{
int array[5]; //an array for the squares
int i; //index into the array
for(i=0; i<5; i++)
{
array[i] = (i+1) * (i+1);
}
for(i=0; i<5; i++)
{
std::cout<<i+1<<" squared is "<<array[i]<<'/n';
}
return (0);
}
7. 用字符变量表示数字的时候要多加小心。它们可能达不到您想要的结果。
比如如下程序,你认为输出是什么呢?
#include <iostream>
int main()
{
char ch; //the flag
ch = 0xFF; //set the flag
//check the flag
if(ch == 0xFF)
{
std::cout<<"Sucessed/n";
}
else
{
std::cout<<"Fails/n";
}
return (0);
}
或许你认为肯定是Sucessed,但输出的缺失Fails,原因是这样的:ch可能是一个有符号的字符。这意味着,如果ch是0xFF,则当它为了比较而转换为有符号整数的时候,您会得到int(ch)=-1(0xFFFFFFF)。这不是0xFF,导致比较失败。
- C - 笔记
- c笔记
- c笔记
- C 笔记
- c 笔记
- C笔记
- C笔记
- C笔记
- C 笔记
- C 笔记
- C笔记
- c 笔记
- C笔记
- C笔记
- C笔记
- C++/C笔记
- 笔记(C/C++)
- C++/C学习笔记
- 简析热得快的单向好友关系
- 如何自己实现IEnumerable和IEnumerator接口以支持foreach语句
- 将有朋自远方来,不亦乐乎
- VC++第一章学习笔记
- VC++学习笔记第二章(1)
- C++捉虫笔记
- Linux中断解析
- 我的光棍节
- 优化SQL Server索引的技巧
- 沪江英语论坛
- Delphi编程控制摄像头 //使用DELPHI使用MS的AVICAP32.DLL就可轻松的实现对摄像头编程
- 我的学习日志10.25
- 存储过程编写经验和优化措施
- 关于Tomcat安装Apache Portable Runtime Utility Library 的问题