简单的问题,我无法在网上找到答案.在可变参数宏中,如何查找参数的数量?如果它有解决方案,我可以使用boost预处理器.
如果它有所不同,我试图转换可变数量的宏参数来增强预处理器序列,列表或数组以进行进一步的重新处理.
我经常发现自己编写辅助调试器方法,返回一个可打印的字符串,给定一些枚举值.这样做的原因是当你通常记录枚举时,你得到的只是一个数字.我讨厌不得不回到我的来源找出那个枚举是什么.所以我会做类似的事情
typedef enum
{
kOne = 1,
kTwo,
kThree,
}
MyEnum;
NSString *debugStringForEnum(MyEnum e)
{
switch ( e )
case kOne:
return @"One";
case kTwo:
return @"Two";
....
}
....
NSLog(@"My debug log: %@", debugStringForEnum(someVariable));
Run Code Online (Sandbox Code Playgroud)
所以我的问题是,有没有办法避免编写所有这些帮助代码,只是为了看到枚举的标签值?
谢谢
有人知道任何C99预处理器魔法允许创建一个由另一个重复N次的字符串组成的字符串吗?
例如
STRREP( "%s ", 3 )
Run Code Online (Sandbox Code Playgroud)
变
"%s %s %s "
Run Code Online (Sandbox Code Playgroud)
经过预处理.
我能想到的唯一一件事就是这样
#define STRREP( str, N ) STRREP_##N( str )
#define STRREP_0(str) ""
#define STRREP_1(str) str
#define STRREP_2(str) str str
#define STRREP_3(str) str str str
...
Run Code Online (Sandbox Code Playgroud)
哪个效果很好,但是很难看,因为我必须手动为每个重复长度定义一个宏.我想与variadic宏一起使用它,宏返回这里显示的宏参数的数量.
#define PP_ARG0_(arg0, ...) arg0
#define PP_REST_(arg0, ...) __VA_ARGS__
#define PP_ARG0(args) PP_ARG0_ args
#define PP_REST(args) PP_REST_ args
#define FUNCTION(name) void name();
#define FUNCTION_TABLE(...) \
FUNCTION(PP_ARG0((__VA_ARGS__))) \
FUNCTION_TABLE(PP_REST((__VA_ARGS__))) \
Run Code Online (Sandbox Code Playgroud)
测试代码:
FUNCTION_TABLE(f1, f2,f3,testA,testB,testC);
Run Code Online (Sandbox Code Playgroud)
显然,由于递归扩展,它只会声明void f1(); ,其余的不会扩展:
void f1(); FUNCTION_TABLE(f2,f3,testA,testB,testC);
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我可以使用什么样的技巧来实现递归扩展?问题是我需要支持许多参数(最多100个),我绝对不能使用boost.
我目前正在寻找计算传递给函数的参数的总大小,以字节为单位.从理论上讲,人们可以sizeof(x)为每一个论点写出来.但是,如果想要为很多功能执行此操作,这将浪费大量时间.我试图找出参数的空间量,这样我就可以分配适量的内存来存储它们并存储它们(适用于各种函数,混合类型).
我正在寻找一个表达式,可以确定非变量函数的所有参数的大小,无论它们的名称如何,无论有多少(在合理范围内,我现在只支持大约64个参数).它可以是一个函数,一个预处理器宏,我对实现是不可知的.我也有兴趣处理可变参数函数,但我很确定这是不可能的,因为当你进入可变参数函数时,你已经丢失了有关数据类型的所有信息.
目前,我发现有三种方法可能会让我这样做.第一个是基于Laurent Deniau的arg计数的概念.从理论上讲,我可以使用一个宏来生成函数头,并做一些类似花哨的步法来获取args的数量并调度到处理每个具有N个参数的个别情况的宏.(见:丑陋).基本上,我只是使用宏对所有函数名称进行别名,然后在每个函数名称上使用sizeof.问题是,我需要为我想要表示的每个参数长度创建一个宏.而且我真的不喜欢做64(或更多)的事情去做一份工作.
第二种方法是尝试遵循Ben Klemer的"更好的可变参数"的方法.我不会使用他的所有方法,但我会尝试生成一个结构,表示函数的arg签名到结构中.然后,我可以尝试获得结构元素的大小(甚至结构本身,如果我所关心的是对空间的保守估计).这有一些问题.首先,它可能只适用于C99兼容的东西(仍在检查).其次,它为每个实现的功能创建了一个额外的结构.这不完全是一个问题,但它仍然存在这样的问题:他的构造结构的方法最终与函数的名称相同(所以你仍然需要引用名称来使用它们).我可能会解决这个问题.
可能的第三种方法是递归宏,但我不确定编译器有多开心.从理论上讲,通过调用表单中的宏来递归地从VA_ARGS中弹出元素是可能的.很明显,当VA_ARG为空时需要暂停规则(以及确保你没有被浮动+符号捕获的东西),但是你明白了.POPPER(arg, ...) POPPER(VA_ARGS) + sizeof(arg)
这些东西中的任何一个都可以让我这样做:
有没有办法生成一个宏来产生数据类型列表的最大大小?
目标
typedef struct {
uint8_t x;
} A;
typedef struct {
uint16_t x;
} B;
typedef struct {
uint8_t x[10];
} C;
#define sizeof_max(A,B,C) //compiles to '10'
Run Code Online (Sandbox Code Playgroud)
用例
通用数据段的不同值映射。
typedef union {
uint8_t array[sizeof_max(A,B,C)];
A iso_hugenum_a;
B ext_a0;
C ext_a1; //and someday down the road 'D' may also get added
} DATA_SEG;
Run Code Online (Sandbox Code Playgroud)
这适用于设备实现基本协议 ISO_HUGENUM_A 的嵌入式应用程序。设备还必须支持此协议的扩展 EXT_A0、EXT_A1、EXT_B0。哎呀,在这种情况下,确实有可能 EXT_C0 出现在路上(糟糕)!
笔记
这里的主要目标是让顶级系统以可扩展和安全的方式了解数据段的大小。当您需要作为数组时,很容易只说“强制转换为数组”。但
在系统级(谁没有给出关于协议的 eff)有读、写和检查(例如 crc)到这个数据段
2 年后,“EXT_C0”可能会出现。我想给继承我代码的可怜人留下一些当 EXT_C0 增长数据段时不会破坏的东西
我希望有一个解决方案,但还没有找到。有任何想法吗?所有大小都将由预处理器生成,因此它似乎是宏的理想候选者。
-贾斯汀