为什么C库使用同名的宏和函数?


20

我正在阅读PJ Plauger的“标准C库”,这真的很有趣。该书不仅说明了如何使用该库,而且还说明了其实现方法。

我已经阅读完本ctype.h节,并且在标头中将函数声明为两个宏AND函数。例如

int isdigit(int);

但是也

#define isdigit(c) (_Ctype[(int)(c)] & _DI)

我不明白为什么两者都使用?

另外,如果我尝试重新创建自己的自定义ctype标头和实现,则只有删除宏(注释中的注释),我才能成功编译。

书中并没有真正解释这方面。有人可以解释一下吗?


C标准中没有任何内容强制编译器将其实现为宏。宏很可能是C没有内联的旧时的残差。尽管如果需要,智能编译器应该能够内联该函数,而无需显式的内联关键字。因此,类似函数的宏之所以存在,是因为编译器是由不擅长编译器的人实现的。

Answers:


23

宏(可能)效率更高,因为它不涉及函数调用。由于它只涉及指针偏移量查找,因此可以更轻松地对其进行优化。

即使程序是在没有宏定义的情况下编译的,函数调用也允许链接到相同的库-如果程序是使用不同的标头或仅在源文件中使用流氓声明进行编译的。例如,如果您有一个编译器,该编译器具有某人的“改进”版本的ctype.h,但没有宏,则该功能在运行时仍将存在以供使用。

如果我们看一下标准:

7.1.4库功能的使用

标头中声明的任何函数都可以另外实现为标头中定义的类函数宏,因此,如果在包含标头时显式声明了库函数,则可以使用以下所示的一种技术来确保不声明该函数受这样的宏影响。可以通过在函数名称中用括号括起来来局部抑制函数的任何宏定义,因为该名称之后不带有表示宏函数名称扩展的左括号。出于相同的语法原因,即使将库函数也定义为宏,也可以采用该库函数的地址。

这意味着如果您编写:

int b = (isdigit)(c);

要么

int (*f)(int) = &isdigit;
int b = f(c);

那么您调用的是实际功能,而不是宏。您还可以合法地写:

#undef isdigit
int b = isdigit(c);

或(在没有#include <ctype.h>直接或传递的源文件中):

extern int isdigit(int);
int b = isdigit(c);

没有宏定义,如何编译程序?
user619818

extern int isdigit(int)例如,@ user619818使用。
ecatmur

只是我很清楚,您的意思是用户没有#include <whatever>,而是添加了int isdigit(int); 在实现文件的顶部。好的,请正确阅读您的回答。
user619818 2012年

拥有一个可调用的函数(相对于内联宏代码)也允许其他语言如Python和Perl与这些功能接口
technosaurus
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.