Имейте макрос 'return' значение
Я использую макрос, и я думаю, что он работает нормально -
#define CStrNullLastNL(str) {char* nl=strrchr(str,'\n'); if(nl){*nl=0;}}
Таким образом, он работает, чтобы обнулить последнюю строку строки в строке, на самом деле ее использовали, чтобы отрубить строку, когда она остается на fgets.
Итак, мне интересно, могу ли я "вернуть" значение из макроса, поэтому его можно вызвать как
func( CStrNullLastNL( cstr ) ) ;
Или мне нужно написать функцию
Ответы
Ответ 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);