Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I am reading 'The Standard C Library' by PJ Plauger which is really interesting. The book explains not only how to USE the library but also how it is implemented.

I have finished reading the ctype.h section and in the header the functions are declared as both macros AND functions. For example

int isdigit(int);

but also

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

I don't understand why BOTH are used?

Also, if I try to recreate my own custom ctype header and implementation, I can only compile successfully if I remove the macro (comment out the define).

This aspect was not really explained in the book. Can someone please explain?

share|improve this question
    
There is nothing in the C standard forcing a compiler to implement it as a macro. The macro is most likely a residue from the old days when C didn't have inlining. Though a smart compiler should be able to inline that function if needed, without an explicit inline keyword. So the function-like macro is only there because the compiler was implemented by someone who was not brilliant at making compilers. –  user29079 Aug 8 '12 at 12:59

1 Answer 1

up vote 15 down vote accepted

The macro is (putatively) more efficient, as it doesn't involve a function call. It can be optimised more easily, as it just involves a pointer offset lookup.

The function call allows linking against the same library even if the program was compiled without the macro definition - if it was compiled with a different header, or just with a rogue declaration inside the source file. Should, for example, you have a compiler which has someone's "improved" version of ctype.h that didn't have the macro, the function would still exist at runtime for use.

If we look at the standard:

7.1.4 Use of library functions

Any function declared in a header may be additionally implemented as a function-like macro defined in the header, so if a library function is declared explicitly when its header is included, one of the techniques shown below can be used to ensure the declaration is not affected by such a macro. Any macro definition of a function can be suppressed locally by enclosing the name of the function in parentheses, because the name is then not followed by the left parenthesis that indicates expansion of a macro function name. For the same syntactic reason, it is permitted to take the address of a library function even if it is also defined as a macro.

That means that if you write:

int b = (isdigit)(c);

or

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

then you are invoking the actual function, not the macro. You can also legally write:

#undef isdigit
int b = isdigit(c);

or (in a source file not having #include <ctype.h> directly or transitively):

extern int isdigit(int);
int b = isdigit(c);
share|improve this answer
    
How could the program be compiled WITHOUT the macro definition? –  user619818 Aug 7 '12 at 12:23
    
@user619818 using extern int isdigit(int), for example. –  ecatmur Aug 7 '12 at 12:30
    
Just so I am clear, you mean user has no #include <whatever> but instead adds int isdigit(int); at top of implementation file. OK, just read through your response properly. –  user619818 Aug 7 '12 at 13:33

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.