#c #protocol-buffers
#c #буферы протокола
Вопрос:
У меня есть странный вариант использования, в котором мне нужно изменить имя переменной, которая была передана в C
#define SET_PROTOBUF_REPEATED(msg_ptr, field_name, src_data, src_data_length)
{
/*
msg_ptr->field_name.len = src_data_length;
*/
// I want to do this
// msg_ptr->n_field_name = src_data_length
/*
msg_ptr->field_name.data = malloc(src_data_length);
memcpy(msg_ptr->field_name.data, src_data, src_data_length);
*/
msg_ptr->field_name = malloc(src_data_length);
memcpy(msg_ptr->field_name, src_data, src_data_length);
}
Поскольку я использую повторяющийся тип в сообщении буфера протокола, переменная длина определяется как
n_variable_name
вместо
variable_name.len
например.
variable_name = frequency
// the length have to be n_frequency
Причина, по которой я хочу иметь макрос, который делает это, заключается в том, что у меня много сообщений protobuf, повторяющих функциональность функции выше. Для удобства чтения и модульности я думаю, что было бы неплохо определить новую функцию, которая позаботится об этом.
Любые советы будут высоко оценены
Спасибо
Комментарии:
1. Попробуйте использовать
##
оператор конкатенации. Таким образом:msg_ptr->n_##field_name = src_data_length;
2. @Don’Tyouworrychild: я почти уверен, что за обратной косой чертой не должен следовать пробел или что-либо другое, кроме новой строки.
3. @jwodder : Да!! Спасибо!! за напоминание мне. Я запутался, на самом деле я однажды столкнулся с этой проблемой, когда я поместил пробел после обратной косой черты, и мне потребовалось некоторое время, чтобы понять это. До того, как я прочитал ваш комментарий, я вспомнил его наоборот !!. 🙂
Ответ №1:
Канонический способ написания многострочного макроса — это обернуть его внутри do ... while(0)
инструкции. Это гарантирует, что макрос работает как единый оператор. Например.:
#define macro(a,b,c)
do {
(a) = (b)*(c);
} while (0) /* No trailing semi-colon */
...
macro (x, y, z);
for (i = 0; i < n; i )
macro (x, y, z); /* This wouldn't work properly without do...while(0) */
Вы должны заключить параметры вашего макроса в круглые скобки, чтобы избежать неожиданностей, когда кто-то передает неожиданные аргументы, например, macro (t, 1 2, 3 4);
вам также нужен вспомогательный макрос для объединения параметров. Возможно, вы ищете что-то вроде этого:
#define CONCAT(x,y) x ## y
#define SET_PROTOBUF_REPEATED(msg_ptr, field_name, src_data, src_data_length)
do {
(msg_ptr)->CONCAT(n_,field_name) = (src_data_length);
(msg_ptr)->(field_name) = malloc((src_data_length));
memcpy((msg_ptr)->(field_name), (src_data), (src_data_length));
} while (0)