C++基础:C++错误
我已经意识到从现在开始我的大部分时间将花在寻找和纠正自己的错误中。
——Maurice Wilkes,1949
错误的种类很多,C++有哪些错误呢?大概看一下!
编译
C++是一种编译语言。这意味着要想让一个程序运行,首先必须将它从人类可读的格式转换为机器可以“理解”的东西。这个转换过程是由一个编译器的程序来做。
我们可以读或者写的东西被称为源代码或者程序文本,计算机可以执行的东西被称为可执行代码,目标代码或者机器代码。
典型的C++源码文件后缀为.cpp或者.h,目标代码的后缀为.obj(Windows)或.o(Unix)。
链接
程序通常由几个单独的部分组成,他们经常由不同的人来开发。程序包含我们编写的部分和C++标准库。这些单独的部分必须被编译,然后生成的目标代码必须被链接起来,形成一个可执行文件。用于将这些部分链接起来的程序(很自然地)被称为链接器。
错误分类
编译时错误:由编译器发现的错误。根据所为违背的语法规则,编译时错误还可以进一步细分,例如:
- 语法错误
- 类型错误
链接时错误:当链接器试图将对象文件链接为可执行文件时发现的错误。
运行时错误:程序运行时发现的错误。运行时错误可以被进一步细分为,
- 由计算机(硬件或操作系统)检测出的错误
- 由库(例如标准库)检测出来的错误。
- 由用户代码检测出来的错误。
逻辑错误:由程序员发现的会导致不正确结果的错误。
语法错误
#include"std_lib_facilities.h"
int area(int length, int width);
int main()
{
int s1 = area(7;
int s2 = area(7
Int s3 = area(7);
int s4 = area('7);
}
上面的每一行都有一个语法错误,即使他们不符合C++语言的语法规范,因此编译器会拒绝它们。为了确定错误,编译器往往会读取更多的信息。这会导致即使一个小错误,编译器也会报告很多繁杂的信息,甚至指向程序中的其他行。因此,在编译器指向的错误行没有错误时不妨检查一下前几行。
类型错误
排除类型错误后,仅接着就是类型错误。
#include"std_lib_facilities.h"
int area(int length, int width);
int main()
{
int s1 = arean(7);//未声明函数
int s2 = area(7);//参数个数不匹配
int s3 = area("seven",3);//第一个参数的类型不匹配
}
## 警告
这些是编译器不会告诉你的,要学会和编译器合作,相互配合,才能尽可能地检查出错误。
#include"std_lib_facilities.h"
int area(int length, int width);
int main()
{
int x4 = area(10,-7); //正确,但宽怎么可能为-7?
int x5 = area(10.7,9.3);//正确,但实际上调用的是(10,9)
char x6= area(100,99999);//正确,但结果越界啦
}
## 链接时错误
一个程序一般包含几个独立的编译部分,称为编译单元。
程序中种的每一个函数在所有编译单元的声明类型必须严格一致。我们使用头文件来保证这一点,并且程序中每个函数只能定义一次。如果上述两条规则的任意一条被违反的话,链机器将会报错。
#include"std_lib_facilities.h"
int area(int length, int width);
int main()
{
int x4 = area(1,2);
}
除非其他源文件中定义了area(),否则这一源文件与当前文件链接时将会报错。
double area(double x, double y){/*.....*/}//不是我们的area
int area(int x, int y, char unit){/*.....*/}//不是我们的area
具有相同名称但类型不同的函数并不会被匹配上。
运行时错误
#include"std_lib_facilities.h"
int area(int length, int width)//计算矩形面积
{
return length*width;
}
int framed_area(int x,int y)//计算内框面积
{
return area(x-2,y-2);
}
int main()
{
int x = -1;
int y = 2;
int z = 1;
//.....
int area1 = area(x,y);
int area2 = framed_area(1,z);
}
在程序中,我们使用的变量x,y,z(而不是使用数值直接作为参数),这使得阅读代码的人和编译器更难发现问题。但这写调用会出现面积为负数。这明显是违背物理和数学规律的。