Подтвердить что ты не робот

Имейте макрос 'return' значение

Я использую макрос, и я думаю, что он работает нормально -

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

Таким образом, он работает, чтобы обнулить последнюю строку строки в строке, на самом деле ее использовали, чтобы отрубить строку, когда она остается на fgets.

Итак, мне интересно, могу ли я "вернуть" значение из макроса, поэтому его можно вызвать как

func( CStrNullLastNL( cstr ) ) ;

Или мне нужно написать функцию

4b9b3361

Ответ 1

Чтобы макрос "возвращал значение", сам макрос должен быть выражением. Ваш макрос представляет собой блок операторов, который не может оценивать выражение.

Вы действительно должны написать функцию inline. Он будет таким же быстрым и гораздо более удобным.

Ответ 2

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

должен работать.

Изменить:... в GCC.

Ответ 3

Макросы не возвращают значения. Макросы сообщают препроцессору заменить все, что есть после #define, с тем, что после объекта после #define. Результат должен быть действительным С++.

Что вы просите, так это сделать следующее:

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

Я не могу придумать хороший способ превратить это во что-то действительное, кроме как просто сделать его настоящим вызовом функции. В этом случае я не уверен, почему макрос будет лучше, чем встроенная функция. Кажется, это то, о чем вы действительно просите.

Ответ 4

Можно ли использовать запятую? Упрощенный пример:

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

Здесь B = SomeMacro (A) "возвращает" результат Permute (A) и назначает его "B".

Ответ 5

Я дал +1 Майку, потому что он на 100% прав, но если вы хотите реализовать это как макрос,

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

Ответ 6

Если вы действительно хотите это сделать, получите компилятор, который поддерживает lambdas стиля С++ 0x:

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

Хотя, поскольку CStrNullLastNL - это в основном функция, вы должны, вероятно, переписать ее как функцию.

Ответ 7

Возврат значения для встроенных функций. И довольно часто упомянутые встроенные функции лучше подходят для задач, чем макросы, которые очень опасны и не имеют безопасного типа.

Ответ 8

Если у вас нет строгого требования использовать только макрос, вы можете сделать что-то вроде этого (пример реальной жизни):

#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;
}

И затем используйте его в своем коде следующим образом:

auto event = Q_XCB_SEND_EVENT_ALIGNED(xcb_unmap_notify_event_t);