I was reading implementation of header in C library, where I came across macro overrides for functions, along with function declarations. I want to know how is this useful, .i.e. either macro should be used or functions, what is the need for override ?
EDIT: Example:
/* ctype.h standard header */
#ifndef _CTYPE
#define _CTYPE
/* Ctype code b i t s */
#define 0x200 /* extra alphabetic */
#define _XS 0x100 /* extra space */
#define _BB 0x80 /* BEL, BS, etc. */
#define _CN 0x40 /*CR, FF, HT, NL, V T */
#define _DI 0x20 /* '0'_' 9' */
#define _LO 0x10 /* 'a'_'2'*/
#define _PU 0x08 /* punctuation */
#define _SP 0x04 /* space */
#define _UP 0x02 /* 'A' _ ' Z ' */
#define _XD 0x01 /* 'Or_'9', 'A'_'Fr, ' a r _ ' f r * /
/* ********declarations********** */
int isalnum(int) , isalpha (int) , iscntrl (iny) , isdigit (int) ;
int isgraph (int) , islower (int) , isprint (int) , ispunct (int) ;
int isspace (int) , isupper (int) , isxdigit (int) ;
int tolower (int) , toupper (int) ;
extern const short *_Ctype, *_Tolower, *_Toupper;
/************ macro overrides*********** */
#define isalnum(c) (_Ctype [ (int)(C) ] & (_DI | _LO | _UP | _XA) )
#define isalpha (c) (_Ctype [ (int)(C) ] & (_LO | _UP | _XA) )
#define i s c n t r l (c) (_Ctype [ (int)(C) ] & (_BB | _CN) )
#define isdigit (c) (_Ctype [ (int)(C) ] & _DI)
#define isgraph (c) (_Ctype [ (int)(C) ] & (_DI | _LO| _PU| _UP | _XA) )
#define islower (c) (_Ctype [ (int)(C) ] & _LO)
#define isprint (c) \
(_Ctype[(int) (c)1 & (_DI| _LO| _PU| _SP| _UP| _XA))
#define ispunct (c) (_Ctype [ ( int ) (c) ] & _PU)
#define isspace (c) (_Ctype [ ( int ) (c) ] & (_CN | _SP | _XS) )
#define isupper (c) (_Ctype [ ( int ) (c) ] & _UP)
#define isxdigit (c) (_Ctype [ ( int ) (c) ] & _XD)
#define tolower (c) _Tolower [ ( int ) (c) ]
#define toupper (c) _Toupper [ ( int ) (c) ]
#endif
*Not to mention function definitions are in separate files
The C standard requires that the functions it specifies must be defined as functions, and they must be declared in the appropriate headers, so that you can pass pointers to functions around.
The C standard allows functions to be overridden by function-like macros.
The standard has a solid block of rules that I've reformatted as a bullet list. The first two bullet points are not directly relevant to the question.
The header in the question illustrates the use of reserved identifiers (§7.1.3 Reserved identifiers](http://port70.net/~nsz/c/c11/n1570.html#7.1.3)). It declares the functions that the
<ctype.h>
header is specified to declare. It provides macros which override those functions in the belief that using those will be quicker than calling a function that implements the array access.With the implementation done that way, if you need to pass a pointer to one of the classification or conversion functions to some other code, you can do so. If only the macros were provided, you'd have to pull some stunts to get actual functions to pass as pointers.
The standard carefully stipulates that a few macros really must be macros —
offsetof()
andva_start()
andva_arg()
are three that spring to mind. But the vast majority of the functions in the standard must be implemented as functions — but may be overridden by a macro if the implementers think that is appropriate.The requirement that the macros be function-like macros is important too. It allows the name to be used without being followed by parentheses to get a pointer to the function. If the macros were not function-like (if the header contained something like
#define isupper _IsUpper
instead of#define isupper(c) _IsUpper(c)
) then it would be impossible to rely on accessing the standard function name — whereas the ¶2 rule allows you to write in your code (without including<ctype.h>
):and you will be guaranteed that there is a function
isupper()
in the library that matches the expectations (even if there is also an_IsUpper()
function).