• C语言的标准库总共分成十五个部分,每个部分用一个头描述。许多编译器都会使用扩展后的库,因此,包含的头通常会多于十五个。额外添加的头当然不属于标准库的范畴,所以,我们不能假设其他的编译器也可以支持这些头。而这些头通常提供一些针对特定机型或特定操作系统的函数,他们可能会提供对屏幕或键盘更多的操作函数,用于支持图形或窗口界面。
  • 标准头主要由函数原型、类型定义以及宏定义组成。如果我们的文件中调用了头中的函数,或是使用了头中定义的类型或宏,那么我们就需要在文件开头将相应的头包含进来,当一个文件包含了多个头时,这些头的顺序无关紧要。

标准库中使用名字的一些限制

  • 任何包含了标准头的文件都必须遵守两条规则:第一该文件不能以任何目的使用在头文件中已经定义过的宏的名字。第二,具有文件作用域的库名尤其是类型名,也不可以在文件中再次使用。
  • 虽然上述这些限制似乎是显而易见的,但c语言还有一些其他的限制可能是你想不到的:
  1. 由一个下划线和一个大写字母开头或有两个下划线开头的标识符,属于标准库中保留的标识符,程序不允许以任何目的使用这种形式的标识符。
  2. 由一个下划线开头的标识符被保留。用于文件作用域内的标识符和标记,除非声明在函数内部,否则不应该使用这类标识符。
  3. 在标准库中所有外部链接的标识符被保留,用于作为需要外部链接的标识符。特别是所有标准库函数的名字都被保留。因此即使文件不需要包含stdio.h,也不应该声明一个外部函数printf,因为在标准库中已经有一个同名的函数了。

使用宏隐藏函数

  • c程序员经常会用宏来替代小的函数,这在标准库中同样很常见。C语言标准允许在头中定义与库函数同名的宏。为了起到保护作用,还要求有实际的函数存在。因此对于库的头,声明一个函数并同时定义一个有相同名字的宏的情况并不少见。

在<ctype.h>中有大量这样成对的函数和宏定义的例子。

  • 例如,用来检测一个其字符是否可以显示的函数isprint。通常的做法是在<ctype.h>中定义 isprint作为一个函数:
int isprint( int c );

并同时把他定义为一个宏:

#define isprint( c ) ((c >= 0x20 && (c) <= 0x7e )
  • 在默认情况下,对isprint的调用会被作为宏调用,因为宏名会在预处理时被替换。那么问题来了,如果在某些情况下,我们需要调用的是一个真实的函数,那又该如何调用同名函数呢? 这里有两种方式可供大家选择:
  1. 通过使用#undef指令来删除宏定义,从而可以访问到真实的函数。
#include <ctype.h>
#undef isprint
  1. 通过给名字加圆括号来屏蔽个别宏调用:
(isprint)(c)

预处理器无法分辨出带圆括号的宏,而编译器不会这么容易被欺骗,他任然可以认出isprint函数。