peng xu
peng xu

Reputation: 415

Is it possible to use #define inside a function?

For example, I saw source code like the following. Can we use #define in a function? How does it work? (more information: this code is what I copied from openvswitch source code):

void *
ofputil_put_action(enum ofputil_action_code code, struct ofpbuf *buf)
{
switch (code) {
case OFPUTIL_ACTION_INVALID:

#define OFPAT13_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) case OFPUTIL_##ENUM:
#include "ofp-util.def"
    OVS_NOT_REACHED();

#define OFPAT10_ACTION(ENUM, STRUCT, NAME)                  \
case OFPUTIL_##ENUM: return ofputil_put_##ENUM(buf);
#define OFPAT11_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME)      \
case OFPUTIL_##ENUM: return ofputil_put_##ENUM(buf);
#define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME)        \
case OFPUTIL_##ENUM: return ofputil_put_##ENUM(buf);
#include "ofp-util.def"
}
OVS_NOT_REACHED();
}

#define OFPAT10_ACTION(ENUM, STRUCT, NAME)                        \
void                                                        \
ofputil_init_##ENUM(struct STRUCT *s)                       \
{                                                           \
    memset(s, 0, sizeof *s);                                \
    s->type = htons(ENUM);                                  \
    s->len = htons(sizeof *s);                              \
}                                                           \
                                                            \
struct STRUCT *                                             \
ofputil_put_##ENUM(struct ofpbuf *buf)                      \
{                                                           \
    struct STRUCT *s = ofpbuf_put_uninit(buf, sizeof *s);   \
    ofputil_init_##ENUM(s);                                 \
    return s;                                               \
}
#define OFPAT11_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
OFPAT10_ACTION(ENUM, STRUCT, NAME)
#define OFPAT13_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
OFPAT10_ACTION(ENUM, STRUCT, NAME)
#define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME)            \
void                                                        \
ofputil_init_##ENUM(struct STRUCT *s)                       \
{                                                           \
    memset(s, 0, sizeof *s);                                \
    s->type = htons(OFPAT10_VENDOR);                        \
    s->len = htons(sizeof *s);                              \
    s->vendor = htonl(NX_VENDOR_ID);                        \
    s->subtype = htons(ENUM);                               \
}                                                           \
                                                            \
struct STRUCT *                                             \
ofputil_put_##ENUM(struct ofpbuf *buf)                      \
{                                                           \
    struct STRUCT *s = ofpbuf_put_uninit(buf, sizeof *s);   \
    ofputil_init_##ENUM(s);                                 \
    return s;                                               \
}
#include "ofp-util.def"

Upvotes: 32

Views: 41962

Answers (6)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476574

#define is a preprocessor directive: it is used to generate the eventual C++ code before it is handled to the compiler that will generate an executable. Therefore code like:

for(int i = 0; i < 54; i++) {
  #define BUFFER_SIZE 1024
}

is not executed 54 times (at the preprocessor level): the preprocessor simply runs over the for loop (not knowing what a for loop is), sees a define statement, associates 1024 with BUFFER_SIZE and continues. Until it reaches the bottom of the file.

You can write #define everywhere since the preprocessor is not really aware of the program itself.

Upvotes: 46

Frank Puffer
Frank Puffer

Reputation: 8215

Sure this is possible. The #define is processed by the preprocessor before the compiler does anything. It is a simple text replacement. The preprocessor doesn't even know if the line of code is inside or outside a function, class or whatever.

By the way, it is generally considered bad style to define preprocessor macros in C++. Most of the things they are used for can be better achieved with templates.

Upvotes: 12

DrC
DrC

Reputation: 7698

You can use it inside a function, but it is not scoped to the function. So, in your example, the second definitions of a macro will be a redefinition and generate an error. You need to use #undef to clear them first.

Upvotes: 7

wallyk
wallyk

Reputation: 57774

Sure. #define is handled by the preprocessor which occurs well before the compiler has any sense of lines of code being inside functions, inside parameters lists, inside data structures, etc.

Since the preprocessor has no concept of C++ functions, it also means that there is no natural scope to macro definitions. So if you want to reuse a macro name, you have to #undef NAME to avoid warnings.

Upvotes: 2

ForceBru
ForceBru

Reputation: 44838

How does it work? All C/C++ files are first processed by... the preprocessor.

It doesn't know anything about C nor C++ syntax. It simply replaces THIS_THING with ANOTHER THING. That's why you can place a #define in functions as well.

Upvotes: 3

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385144

You can use #define anywhere you want. It has no knowledge of functions and is not bound by their scope. As the preprocessor scans the file from top-to-bottom it processes #defines as it sees them. Do not be misled (by silly code like this!) into thinking that the #define is somehow processed only when the function is called; it's not.

Upvotes: 4

Related Questions