1

我刚刚编译了NIST RS274NGC G-Code Interpreter并看到来自 gcc 的令人难以置信的 890 警告。

其中 200 个是由这个数组引起的:

char * _rs274ngc_errors[] = {
/*   0 */ "No error",
/*   1 */ "No error",
/*   2 */ "No error",
/*   3 */ "No error",
/*   4 */ "A file is already open", // rs274ngc_open
<...>

根据我的基本理解,应该是const char *.

然后我看到了这些宏(它们实际上在不同的 .cc 文件中出现了好几次):

#define AND              &&
#define IS               ==
#define ISNT             !=
#define MAX(x, y)        ((x) > (y) ? (x) : (y))
#define NOT              !
#define OR               ||
#define SET_TO           =

然后我看到了很多suggest braces around empty body in an 'else' statement [-Wempty-body]由非常奇怪的控制流改变宏引起的警告(是的,还有悬空的其他!):

#define PRINT0(control) if (1)                        \
          {fprintf(_outfile, "%5d \n", _line_number++); \
           print_nc_line_number();                    \
           fprintf(_outfile, control);                \
          } else

报告表明

A.5 解释器错误

解释器没有已知的错误

所有这一切都让我想知道——为什么它写得这么奇怪?我可以理解 PRINT0 之类的宏 - C 中的错误处理可能会很痛苦 - 但为什么有人会使用SET_TO而不是=呢?

我可以相信所有这些代码都是生成的,但不能以无警告的方式生成吗?

无论如何,我不是专家,我只是很好奇。

4

2 回答 2

2

正如 Hans 和 Foad 所指出的,这是当时的常态。K&R C在语言的发明者 Brian Kernighan 和 Dennis Ritchie 之后,它被称为。(请注意,K&R C 也可以参考他们在编写第一本关于该语言的书时普及的格式样式。)

K&R C 非常宽容 C99 或 C11 模式下的编译器会将其视为 UB(未定义行为)或完全语法错误的事情,例如定义带 args 的函数而不指定 args 的类型。那时,假设这样的函数采用 int args。

IIRC 对该语言的第一次大修是 ANSI C '89;计算机能力、编译器和语言的流行在它的发明和标准化之间发生了巨大的变化。

如果您对陈旧的 C 感兴趣,您可能希望查看 Bourne shell 的源代码。引用维基百科的Bourne Shell文章:

Stephen Bourne 的编码风格受到他使用 ALGOL 68C 编译器经验的影响......

... Bourne 利用一些宏使 C 源代码具有 ALGOL 68 风格。这些宏(以及在 Unix 4.2BSD 版本中分发的手指命令)激发了 IOCCC – 国际混淆 C 代码竞赛。

代码的实际示例可以在rsc 的网站上找到,并且(我假设是)完整的源代码可以在这里找到。


顺便说一句,如果您认为收到的警告数量很多,您应该尝试打开其他警告。有很多可靠且有用的工具,但默认情况下并未启用,尽管我没有它们的最新列表。-Wall -Wextra将是一个不错的开始。

于 2019-11-30T05:53:23.867 回答
1

实际上,如果您从当时的计算机科学或数学的角度来看,这是有道理的。“C”语法现在如此主流以至于我们甚至都没有考虑它。但当时=是平等的,它仍然是在数学背景下。用作=赋值运算符是一个奇怪且相当混乱的选择。新手程序员有时会将其与数学等式混淆。相比之下,R 使用<-or ->,Maxima 和 Modelica 使用:=,这些都是数学家设计的语言。and, or,not也是is不错的选择,例如在 Python 中使用。从编程的角度来看,以这种方式使用预处理宏是可怕的想法,但如果你考虑一下基本原理,它实际上是C被指责。

于 2019-04-05T20:25:20.503 回答