Professional Documents
Culture Documents
C Faq5
C Faq5
4
What's the best way to write a multi-statement macro?
-----------------------------------------------------------------------
The usual goal is to write a macro that can be invoked as if it were a
statement consisting of a single function call. This means that the
``caller'' will be supplying the final semicolon, so the macro body
should not. The macro body cannot therefore be a simple brace-enclosed
compound statement, because syntax errors would result if it were
invoked (apparently as a single statement, but with a resultant extra
semicolon) as the if branch of an if/else statement with an explicit
else clause.
----------------------
Question 10.26
How can I write a macro which takes a variable number of arguments?
-----------------------------------------------------------------------
One popular trick is to define and invoke the macro with a single,
parenthesized ``argument'' which in the macro expansion becomes the
entire argument list, parentheses and all, for a function such as
printf:
The obvious disadvantage is that the caller must always remember to use
the extra parentheses.
DEBUG("i = %d" _ i)
------------------------------------------------------------------------
--------
if(first == NULL)
return NULL;
len = strlen(first);
va_start(argp, first);
va_end(argp);
if(retbuf == NULL)
return NULL; /* error */
(void)strcpy(retbuf, first);
return retbuf;
}
Note the cast on the last argument; see questions 5.2 and 15.3. (Also
note that the caller must free the returned, malloc'ed storage.)
--------------------
Section 6. C Preprocessor
6.2: I have some old code that tries to construct identifiers with a
macro like
#define Func() do { \
/* declarations */ \
stmt1; \
stmt2; \
/* ... */ \
} while(0) /* (no trailing ; ) */
#ifndef HEADERUSED
#define HEADERUSED
...header file contents...
#endif
References: ANSI Sec. 2.1.1.2 pp. 6-7, Sec. 3.8.1 p. 87 footnote 83.
6.7: I've got this tricky processing I want to do at compile time and I
can't figure out a way to get cpp to do it.
cpp is not intended as a general-purpose preprocessor. Rather than
forcing it to do something inappropriate, consider writing your own
little special-purpose preprocessing tool, instead. You can easily get a
utility like make(1) to run it for you automatically.
6.8: I inherited some code which contains far too many #ifdef's for my
taste. How can I preprocess the code to leave only one conditional
compilation set, without running it through cpp and expanding all of the
#include's and #define's as well?
There are programs floating around called unifdef, rmifdef, and scpp
which do exactly this. (See question 17.12.)
6.10: How can I write a cpp macro which takes a variable number of
arguments?
One popular trick is to define the macro with a single argument, and
call it with a double set of parentheses, which appear to the
preprocessor to indicate a single argument:
------------------------------------------------------------------------
--------
Question 1.14
I can't seem to define a linked list successfully. I tried
typedef struct {
char *item;
NODEPTR next;
} *NODEPTR;
------------------------------------------------------------------------
--------
struct node {
char *item;
struct node *next;
};
------------------
Question 1.21
How do I declare an array of N pointers to functions returning pointers
to functions returning pointers to characters?
------------------------------------------------------------------------
--------
The first part of this question can be answered in at least three ways:
char *(*(*a[N])())();
Build the declaration up incrementally, using typedefs:
typedef char *pc; /* pointer to char */
typedef pc fpc(); /* function returning pointer to char */
typedef fpc *pfpc; /* pointer to above */
typedef pfpc fpfpc(); /* function returning... */
typedef fpfpc *pfpfpc; /* pointer to... */
pfpfpc a[N]; /* array of... */
Use the cdecl program, which turns English into C and vice versa:
cdecl> declare a as array of pointer to function returning
pointer to function returning pointer to char
char *(*(*a[])())()
-----------------------
Question 1.22
How can I declare a function that can return a pointer to a function of
the same type? I'm building a state machine with one function for each
state, each of which returns a pointer to the function for the next
state. But I can't find a way to declare the functions.
------------------------------------------------------------------------
--------
------------------------------------------------------------------------
--------
Question 1.32
What is the difference between these initializations?
------------------------------------------------------------------------
--------
----------------------
Question 2.4
What's the best way of implementing opaque (abstract) data types in C?
------------------------------------------------------------------------
--------
---------------
Question 2.7
I heard that structures could be assigned to variables and passed to and
from functions, but K&R1 says not.
------------------------------------------------------------------------
--------
What K&R1 said was that the restrictions on structure operations would
be lifted in a forthcoming version of the compiler, and in fact
structure assignment and passing were fully functional in Ritchie's
compiler even as K&R1 was being published. Although a few early C
compilers lacked these operations, all modern compilers support them,
and they are part of the ANSI C standard, so there should be no
reluctance to use them. [footnote]
--------------
Question 2.8
Why can't you compare structures?
------------------------------------------------------------------------
--------
-------------------
Question 2.13
Why does sizeof report a larger size than I expect for a structure type,
as if there were padding at the end?
------------------------------------------------------------------------
--------