在 C 中打印出非均匀参数列表
Print out list of non-uniform parameters in C
我有一些设备有很多不同的参数,可以是 bool、char、int、float、string 等等。我需要在某个 AJAX 数组中一次打印它们(用于 Web 界面控件)。我必须使用纯 C,并且此代码在某些具有狭窄 ROM/RAM 资源的 MCU 上将是 运行。可能的方法是什么?如果它们都是统一的,比如 int 的,我可以只使用 array:
Uint16_t params[PARAM_1]=GetParam(PARAM_1);
PrintParams(¶ms)
{
For(iii=0;iii<MAX_COUNT;iii++)
{
HTTPPrint(params[iii]);
}
}
但他们不是。
根本不对它们进行分组将很容易出错然后 adding/removing 参数,并且还有开销:
Uint16_t param1= GetParam1();
Float param2= GetParam2();
PrintParams(¶ms)
{
HTTPPrint(param1);
HTTPPrint(param2);
//another 100+ parameters to print
}
使用一些高级的数据结构,比如链表会带来巨大的开销(对于任何一个字符至少需要存储4字节的指针)。
也许还有其他方法可以做到?
Tagged union 允许您将类型信息与数据一起携带,并且不会占用很多 space:
enum type_t {
kTypeChar = 1,
kTypeInt = 2
};
union data_t {
char i8;
int i32;
};
struct anytype {
enum type_t tag;
union data_t data;
};
你可以直接对储值类型做case-analysis。尽管它确实在类型标签和值不匹配方面留下了一些错误空间:
struct anytype v = GetParam(PARAM_1);
switch (v->tag) {
case kTypeChar: HTTPPrintChar(v->data.i8); break;
case kTypeInt: HTTPPrintInt(v->data.i32); break;
default: assert(0);
};
或者您可以在每种类型中添加一个多态打印处理程序,以使其不易出错。虽然它会消耗额外的 space 来携带所有数据项的指针,但它不太容易出错并且更容易使用。
typedef void (*print_func_t) (struct polytype* self);
struct polytype {
print_func_t print;
union data_t data;
};
void print_char(struct polytype* self) {
HTTPPrintChar(self->data.i8);
}
void print_int(struct polytype* self) {
HTTPPrintChar(self->data.i32);
}
struct polytype t = GetParam(PARAM_1); /* GetParam sets proper print fptr based on param type */
t.print(&t);
我有一些设备有很多不同的参数,可以是 bool、char、int、float、string 等等。我需要在某个 AJAX 数组中一次打印它们(用于 Web 界面控件)。我必须使用纯 C,并且此代码在某些具有狭窄 ROM/RAM 资源的 MCU 上将是 运行。可能的方法是什么?如果它们都是统一的,比如 int 的,我可以只使用 array:
Uint16_t params[PARAM_1]=GetParam(PARAM_1);
PrintParams(¶ms)
{
For(iii=0;iii<MAX_COUNT;iii++)
{
HTTPPrint(params[iii]);
}
}
但他们不是。 根本不对它们进行分组将很容易出错然后 adding/removing 参数,并且还有开销:
Uint16_t param1= GetParam1();
Float param2= GetParam2();
PrintParams(¶ms)
{
HTTPPrint(param1);
HTTPPrint(param2);
//another 100+ parameters to print
}
使用一些高级的数据结构,比如链表会带来巨大的开销(对于任何一个字符至少需要存储4字节的指针)。 也许还有其他方法可以做到?
Tagged union 允许您将类型信息与数据一起携带,并且不会占用很多 space:
enum type_t {
kTypeChar = 1,
kTypeInt = 2
};
union data_t {
char i8;
int i32;
};
struct anytype {
enum type_t tag;
union data_t data;
};
你可以直接对储值类型做case-analysis。尽管它确实在类型标签和值不匹配方面留下了一些错误空间:
struct anytype v = GetParam(PARAM_1);
switch (v->tag) {
case kTypeChar: HTTPPrintChar(v->data.i8); break;
case kTypeInt: HTTPPrintInt(v->data.i32); break;
default: assert(0);
};
或者您可以在每种类型中添加一个多态打印处理程序,以使其不易出错。虽然它会消耗额外的 space 来携带所有数据项的指针,但它不太容易出错并且更容易使用。
typedef void (*print_func_t) (struct polytype* self);
struct polytype {
print_func_t print;
union data_t data;
};
void print_char(struct polytype* self) {
HTTPPrintChar(self->data.i8);
}
void print_int(struct polytype* self) {
HTTPPrintChar(self->data.i32);
}
struct polytype t = GetParam(PARAM_1); /* GetParam sets proper print fptr based on param type */
t.print(&t);