isupper() 是宏还是函数?

Is isupper() a macro or a function?

我正在阅读一本关于 C++ 的书(Ulla Kirch-Prinz 和 Peter Prinz 所著的《C++ 编程完整指南》;ISBN:0-7637-1817-3)和它提到 isupper() 以及 islower()、isalpha()、isdigit()、isalnum()、isspace() 和 isprint() 是 用于字符分类的宏

我觉得这种奇怪的原因有两个:

  1. 在同一本书中,它谈到了即使宏可以有参数,它们本质上仍然只是用定义填充的占位符名称。这看起来很奇怪,因为我不知道什么样的替换文本会有条件地运行。这听起来更符合函数或内置操作(如 sizeof)。

  2. 这也很奇怪,因为我听说有人称这些函数为宏,而我也听说有人称它们为宏。

任何解释将不胜感激。我对此还比较陌生,所以我仍在努力弄清楚这一切。谢谢。

除了评论中讨论的历史,

isupper 正式是 C++ 中的 函数

请参阅 link 中的文档。它显示签名、命名空间和其他详细信息。

编辑:(回复评论)

历史上,可能是从 C 演化而来的宏。因为那是实现定义的。

如果您想知道该宏是如何定义的,请参阅 this

标准 C(据我所知,在其所有版本中)允许任何标准库函数被定义为宏。在当前的 C 标准中,它隐藏在 §7.1.4(库函数的使用)第 1 段中:

Any function declared in a header may be additionally implemented as a function-like macro defined in the header… Any invocation of a library function that is implemented as a macro shall expand to code that evaluates each of its arguments exactly once, fully protected by parentheses where necessary, so it is generally safe to use arbitrary expressions as arguments.

宏可以由标准库实现定义以提供效率(虽然这不像以前那么重要,现在大多数编译器将内联函数),但函数也需要定义为具有完全相同语义的函数,这意味着您可以在不包含 header 的情况下使用该函数(只要您提供正确的函数原型)并且您可以获取函数的地址。

而且,正如我引用的第二句话所指出的,您不必担心宏可能产生的奇怪副作用,例如对其参数的多次求值——除非 函数的描述另有说明。 (一个这样的函数是 getc,它在语义上与 fgetc 相同,除了 getc 被允许作为一个宏来实现,它确实对其参数求值不止一次。)

这些函数从来都不是只作为宏实现的(至少,不是在符合标准的库中)。但是曾经有一段时间,将简单的功能也实现为宏非常普遍,以至于有些人只是指望现有的宏。或者谈论它们,好像那是唯一的实现。

None C++中就是这样。 C++ 要求函数是函数(宏是宏),并且函数在命名空间中。这并没有使 C++ 与 C 不兼容;只需要 C++ header 声明与 C 共享的函数(即名称以 c 开头的函数)到 #undef 所有(潜在的)宏定义后包含对应的Cheader.