3-1 语法和语义错误

软件错误无处不在。它们既容易产生,又难以发现。本章将探讨与在C++程序中查找和消除错误相关的话题,包括学习如何使用集成开发环境(IDE)内置的调试器。

尽管调试工具和技术不属于C++标准范畴,但掌握查找和消除程序中错误的能力,却是成为优秀程序员的关键要素。因此我们将花些篇幅讲解相关主题,确保当你编写的程序日益复杂时,诊断和修复问题的能力也能同步提升。

若你曾用其他编程语言调试过程序,本章内容对你而言将颇为熟悉。


语法错误

编程本身充满挑战,而C++又是一种颇具个性化的语言。二者结合之下,出错的可能性便大大增加。错误通常分为两类:语法错误和语义错误(逻辑错误)。

语法错误syntax error发生在编写的语句不符合C++语言语法规则时,包括漏写分号、括号或大括号不匹配等错误。例如以下程序就包含多个语法错误:

#include <iostream>

int main( // missing closing brace
{
    int 1x; // variable name can't start with number
    std::cout << "Hi there"; << x +++ << '\n'; // extraneous semicolon, operator+++ does not exist
    return 0 // missing semicolon at end of statement
}

image

幸运的是,编译器会检测到语法错误并发出编译警告或错误,因此您可以轻松识别并修复问题。之后只需反复编译,直到所有错误都消除即可。


语义错误

语义错误semantic error是指语义层面的错误。当语句在语法上正确,但违反了语言的其他规则,或未能实现程序员的预期时,就会发生此类错误。

某些语义错误可被编译器捕获,常见示例包括使用未声明变量、类型不匹配(在某处使用了类型错误的对象)等。

例如,以下程序包含多个编译时语义错误:

int main()
{
    5 = x; // x not declared, cannot assign a value to 5
    return "hello"; // "hello" cannot be converted to an int
}

其他语义错误仅在运行时显现。有时这些错误会导致程序崩溃,例如除以零的情况:

#include <iostream>

int main()
{
    int a { 10 };
    int b { 0 };
    std::cout << a << " / " << b << " = " << a / b << '\n'; // division by 0 is undefined in mathematics
    return 0;
}

image

这些操作通常只会产生错误的值或行为:

#include <iostream>

int main()
{
    int x; // no initializer provided
    std::cout << x << '\n'; // Use of uninitialized variable leads to undefined result

    return 0;
}

image

或者

#include <iostream>

int add(int x, int y) // this function is supposed to perform addition
{
    return x - y; // but it doesn't due to the wrong operator being used
}

int main()
{
    std::cout << "5 + 3 = " << add(5, 3) << '\n'; // should produce 8, but produces 2

    return 0;
}

或者

#include <iostream>

int main()
{
    return 0; // function returns here

    std::cout << "Hello, world!\n"; // so this never executes
}

在上例中,错误相当容易发现。但在大多数非平凡程序中,仅凭肉眼审阅代码很难发现运行时语义错误。此时调试技术便能派上用场。

posted @ 2026-02-10 15:50  游翔  阅读(0)  评论(0)    收藏  举报