Why are some library routines implemented as macro

2019-08-05 02:46发布

问题:

I am struggling to put it clearly in words. So let me put it in parts. The contexts are from the C book by Mike Banahan (Links provided with each part below). Here are my questions as bullet points in bold:

  • Why are some library functions simultaneously implemented as macros too? What's the need? Here's what I read from the book (Section 9.1.1):

A last general point is that many of the library routines may be implemented as macros, provided that there will be no problems to do with side-effects (as Chapter 7 describes). The Standard guarantees that, if a function is normally implemented as a macro, there will also be a true function provided to do the same job. To use the real function, either undefine the macro name with #undef, or enclose its name in parentheses, which ensures that it won't be treated as a macro:

  • va_start, as we know it, is a function or macro? The following text from the book is the source of confusion as it implies both in the same breath, in adjacent lines!! (Section 9.9)

Before any attempt can be made to access a variable argument list, va_start must be called. It is defined as

 #include <stdarg.h>
void va_start(va_list ap, parmN); 

The va_start macro initializes ap for subsequent use by the functions va_arg and va_end.

  • And finally, the most confusing part. In the following line, it's clearly written that va_arg is a macro and goes on to show how it is implemented. But how can a macro be implemented without a #define keyword, and that too with return type ('type') as if it were a function? (Section 9.9)

Once initialized, the arguments supplied can be accessed sequentially by means of the va_arg macro. This is peculiar because the type returned is determined by an argument to the macro. Note that this is impossible to implement as a true function, only as a macro. It is defined as

#include <stdarg.h>
type va_arg(va_list ap, type);

Your answers will be very much appreciated. Thank you.

回答1:

These are two distinct questions.

Firstly, va_start, va_arg and va_end are guaranteed to be macros. va_arg cannot be a function, because its second argument is a type rather than a value.

As to why some functions are also macros: because you want a call to be inlined, making it fast, but you might also want to take its address and put that in a function pointer:

int (*function_pointer)(int, FILE *) = &(putc);