我有一个 C 结构体,我为其编写了
printf
格式和值宏:
#define FREQ_MAX_SYMBOL 8
struct freq {
int num_symbols; // <= FREQ_MAX_SYMBOL
int tot_freq; // sum of all the frequencies
int req_freqs[FREQ_MAX_SYMBOL]; // required frequencies
int cur_freqs[FREQ_MAX_SYMBOL]; // current frequencies
};
#define FREQ_FORMAT "{num_symbols: %i, tot_freq: %i, req_freqs: [%i,%i,%i,%i,%i,%i.%i,%i], cur_freqs: [%i,%i,%i,%i,%i,%i,%i,%i]}"
#define FREQ_VALUES(f) f->num_symbols, f->tot_freq, \
f->req_freqs[0], f->req_freqs[1], f->req_freqs[2], f->req_freqs[3], f->req_freqs[4], f->req_freqs[5], f->req_freqs[6], f->req_freqs[7], \
f->cur_freqs[0], f->cur_freqs[1], f->cur_freqs[2], f->cur_freqs[3], f->cur_freqs[4], f->cur_freqs[5], f->cur_freqs[6], f->cur_freqs[7]
是否可以更改宏,以便它们只为
num_symbols
和 req_freqs[]
创建 cur_freqs[]
数量的格式和值?
例如如果
num_symbols == 2
仅应打印 req_freqs[0]
和 [1]
和 cur_freqs[0]
和 [1]
。
一开始这可能不是一个好主意,在运行时使用函数+循环会更好。特别是因为您已经通过使用
printf
将性能抛到了九霄云外,所以在编译时执行所有这些操作没有太多争论。
话虽这么说,如果你坚持使用宏,并且如果你能保证
num_symbols
成员对应于 FREQ_MAX_SYMBOL
,那么你可以制作出一个笨重、邪恶的宏列表,如下所示:
#define FREQ_FORMAT_1 "{num_symbols: %i, tot_freq: %i, req_freqs: [%i], cur_freqs: [%i]}"
#define FREQ_FORMAT_2 "{num_symbols: %i, tot_freq: %i, req_freqs: [%i,%i], cur_freqs: [%i,%i]}"
#define FREQ_FORMAT_3 "{num_symbols: %i, tot_freq: %i, req_freqs: [%i,%i,%i], cur_freqs: [%i,%i,%i]}"
#define FREQ_PARAM_1 (f).req_freqs[0], \
(f).cur_freqs[0]
#define FREQ_PARAM_2 (f).req_freqs[0], (f).req_freqs[1], \
(f).cur_freqs[0], (f).cur_freqs[1]
#define FREQ_PARAM_3 (f).req_freqs[0], (f).req_freqs[1], (f).req_freqs[2], \
(f).cur_freqs[0], (f).cur_freqs[1], (f).cur_freqs[2]
您需要为您支持的论点数量设置一个上限。 然后你可以这样称呼它们:
#define CONCAT_(a,b) a##b
#define CONCAT(a,b) CONCAT_(a,b)
#define FREQ_FORMAT CONCAT(FREQ_FORMAT_, FREQ_MAX_SYMBOL)
#define FREQ_VALUES(f) (f).num_symbols, (f).tot_freq, CONCAT(FREQ_PARAM_, FREQ_MAX_SYMBOL)
至少第一个宏
FREQ_FORMAT
需要额外级别的宏扩展,因为它是类似对象的宏而不是类似函数的宏。因此,我们需要一个辅助宏来扩展该宏。然后是在进一步宏扩展之前应用 ## 的常见问题,因此需要位于自己的辅助宏中。
完整示例:
#include <stdio.h>
#define FREQ_MAX_SYMBOL 3
struct freq {
int num_symbols; // <= FREQ_MAX_SYMBOL
int tot_freq; // sum of all the frequencies
int req_freqs[FREQ_MAX_SYMBOL]; // required frequencies
int cur_freqs[FREQ_MAX_SYMBOL]; // current frequencies
};
#define FREQ_FORMAT_1 "{num_symbols: %i, tot_freq: %i, req_freqs: [%i], cur_freqs: [%i]}"
#define FREQ_FORMAT_2 "{num_symbols: %i, tot_freq: %i, req_freqs: [%i,%i], cur_freqs: [%i,%i]}"
#define FREQ_FORMAT_3 "{num_symbols: %i, tot_freq: %i, req_freqs: [%i,%i,%i], cur_freqs: [%i,%i,%i]}"
#define FREQ_PARAM_1 (f).req_freqs[0], \
(f).cur_freqs[0]
#define FREQ_PARAM_2 (f).req_freqs[0], (f).req_freqs[1], \
(f).cur_freqs[0], (f).cur_freqs[1]
#define FREQ_PARAM_3 (f).req_freqs[0], (f).req_freqs[1], (f).req_freqs[2], \
(f).cur_freqs[0], (f).cur_freqs[1], (f).cur_freqs[2]
#define CONCAT_(a,b) a##b
#define CONCAT(a,b) CONCAT_(a,b)
#define FREQ_FORMAT CONCAT(FREQ_FORMAT_, FREQ_MAX_SYMBOL)
#define FREQ_VALUES(f) (f).num_symbols, (f).tot_freq, CONCAT(FREQ_PARAM_, FREQ_MAX_SYMBOL)
int main()
{
struct freq f =
{
.num_symbols = FREQ_MAX_SYMBOL,
.tot_freq = 123,
.req_freqs = {1,2,3},
.cur_freqs = {4,5,6},
};
printf(FREQ_FORMAT, FREQ_VALUES(f));
}
输出:
{num_symbols: 3, tot_freq: 123, req_freqs: [1,2,3], cur_freqs: [4,5,6]}