c - 为什么编译器不报告缺少分号?

标签 c freeform

我有这个简单的程序:

#include <stdio.h>

struct S
{
    int i;
};

void swap(struct S *a, struct S *b)
{
    struct S temp;
    temp = *a    /* Oops, missing a semicolon here... */
    *a = *b;
    *b = temp;
}

int main(void)
{
    struct S a = { 1 };
    struct S b = { 2 };

    swap(&a, &b);
}

如图所示on e.g. ideone.com这给出了一个错误:

prog.c: In function 'swap':
prog.c:12:5: error: invalid operands to binary * (have 'struct S' and 'struct S *')
     *a = *b;
     ^

为什么编译器没有检测到丢失的分号?


注意:这个问题及其答案的动机是 this question .虽然有 other questions与此类似,我没有发现任何提及 C 语言的自由形式能力的内容,这是导致此错误和相关错误的原因。

最佳答案

C 是一种自由格式 语言。这意味着您可以用多种方式格式化它,它仍然是一个合法的程序。

例如这样的语句

a = b * c;

可以这样写

a=b*c;

或者喜欢

a
=
b
*
c
;

所以当编译器看到这些行时

temp = *a
*a = *b;

它认为它意味着

temp = *a * a = *b;

这当然不是一个有效的表达式,编译器会提示这个而不是缺少分号。它无效的原因是因为 a 是一个指向结构的指针,所以 *a * a 试图乘以一个结构实例(*a) 以及指向结构 (a) 的指针。

虽然编译器无法检测到丢失的分号,但它还会在错误行上报告完全不相关的错误。注意到这一点很重要,因为无论您如何查看报告错误的行,那里都没有错误。有时像这样的问题需要您查看行以查看它们是否正常且没有错误。

有时您甚至必须查看另一个文件才能找到错误。例如,如果头文件在头文件中最后一次定义结构,并且缺少终止结构的分号,则错误不会出现在头文件中,而是出现在包含头文件的文件中。

有时情况会变得更糟:如果您包含两个(或更多)头文件,并且第一个包含不完整的声明,则很可能会在第二个头文件中指出语法错误。


与此相关的是跟进错误的概念。一些错误,通常是由于实际上缺少分号,被报告为多个 错误。这就是为什么在修复错误时从头开始很重要,因为修复第一个错误可能会使多个错误消失。

这当然会导致一次修复一个错误和频繁的重新编译,这对于大型项目来说可能很麻烦。不过,识别此类后续错误需要经验,在看到它们几次后,更容易挖掘出真正的错误并在每次重新编译时修复多个错误。

关于c - 为什么编译器不报告缺少分号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40135392/

相关文章:

一个套接字可以加入多个多播组吗?

java - 将自由格式的 XML/JSON 映射到 Moxy/JAXB 注释类

statistics - 如何对调查中问题的自由形式答案进行分类和表格化?

使用calloc后C访问冲突

c - 没有强制类型转换错误的链表指针

ios - 最初不可滚动的scrollView?

delphi - 自由格式报告工具

javascript - 使用javascript从下拉列表中删除重复项

php - 用 C 创建 PHP 扩展

C 宏使用文字与变量产生不同的结果