如何在 C 宏中创建可变数量的 printf 格式和值?

问题描述 投票:0回答:1

我有一个 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]

c struct macros printf
1个回答
0
投票

一开始这可能不是一个好主意,在运行时使用函数+循环会更好。特别是因为您已经通过使用

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]}
© www.soinside.com 2019 - 2024. All rights reserved.