简体   繁体   中英

Have macro 'return' a value

I'm using a macro and I think it works fine -

#define CStrNullLastNL(str) {char* nl=strrchr(str,'\n'); if(nl){*nl=0;}}

So it works to zero out the last newline in a string, really its used to chop off the linebreak when it gets left on by fgets.

So, I'm wondering if I can "return" a value from the macro, so it can be called like

func( CStrNullLastNL( cstr ) ) ;

Or will I have to write a function

#define CStrNullLastNL(str) ({ \
    char* nl=strrchr(str,'\n');\
    if(nl){*nl=0;} \
    nl; \
})

should work.

Edit: ... in GCC.

For a macro to "return a value", the macro itself has to be an expression. Your macro is a statement block, which cannot evaluate to an expression.

You really ought to write an inline function. It will be just as fast and far more maintainable.

Macro's don't return values. Macros tell the preprocessor to replace whatever is after the #define with whatever is after the thing after the #define . The result has to be valid C++.

What you're asking for is how to make the following valid:

func( {char* nl=strrchr(str,'\n'); if(nl){*nl=0;}} );

I can't think of a good way to turn that into something valid, other than just making it a real function call. In this case, I'm not sure why a macro would be better than an inline function. That's seems to be what you're really asking for.

If you really want to do this, get a compiler that supports C++0x style lambdas:

#define CStrNullLastNL(str) [](char *blah) {char* nl=strrchr(blah,'\n'); if(nl){*nl=0;} return blah;}(str)

Although since CStrNullLastNL is basically a function you should probably rewrite it as a function.

Can you use the comma operator? Simplified example:

#define SomeMacro(A) ( DoWork(A), Permute(A) )

Here B=SomeMacro(A) "returns" the result of Permute(A) and assigns it to "B".

I gave +1 to Mike because he's 100% right, but if you want to implement this as a macro,

char *CStrNullLastNL_nl; // "private" global variable
#define nl ::CStrNullLastNL_nl // "locally" redeclare it
#define CStrNullLastNL( str ) ( \
    ( nl = strrchr( str, '\n') ), /* find newline if any */ \
    nl && ( *nl = 0 ), /* if found, null out */ \
    (char*) nl /* cast to rvalue and "return" */ \
OR  nl? str : NULL /* return input or NULL or whatever you like */
)
#undef nl // done with local usage

If you don't have a strict requirement to use only macro, you can do something like this (real life example):

#define Q_XCB_SEND_EVENT_ALIGNED(T) \
    q_xcb_send_event_aligned<T>()

template<typename T> inline
T q_xcb_send_event_aligned()
{
    union {
        T event;
        char padding[32];
    } event;

    memset(&event, 0, sizeof(event));
    return event.event;
}

And then use it in your code like this:

auto event = Q_XCB_SEND_EVENT_ALIGNED(xcb_unmap_notify_event_t);

Returning a value is what inline functions are for. And quite often, said inline functions are better suited to tasks than macros, which are very dangerous and have no type safetly.

to return value from macro:

bool my_function(int a) {
    if (a > 100)return true;
    return false;
}
bool val = my_function(200);

#define my_macro(ret_val,a){\
    if(a > 100 ) ret_val = true;\
    ret_val = false;\
}
bool val; my_macro(val, 200);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM