【发布时间】:2019-05-14 21:36:29
【问题描述】:
我有一个棘手但有趣的问题。坚持住!
假设我编写嵌入式代码,并且我在一个系统中,我必须以 16 位无符号存储值以与其他系统兼容。有些值有小数部分,但幸运的是我提前知道了分隔符的位置(定点)。
现在让我们考虑这个结构:
typedef struct{
// pointer to a function that computes the "real" value
float (*getRealValue)(void);
// pointer to a function that computes a "stringified" value
bool (*getCustomString)(char *);
} var_info_t;
让我们声明一个变量 var1,它是一个温度:
uint16_t var1 = 1530; // means 15.3°C
float var1_toFloat(void){ return (float)var1/100; } // should return 15.3
var_info_t var1_info = { .getRealValue = var1_toFloat, .getCustomString = NULL };
还有另一个变量 var2,它恰好更像一个布尔值:
uint16_t var2 = 1; // means Enabled
bool var2_toString(char* buffer){ // should write "Enabled"
if(buffer) sprintf(buffer, "%s", var2 ? "Enabled" : "Disabled");
return true;
}
var_info_t var2_info = { .getRealValue = NULL, .getCustomString = var2_toString };
现在我想将这些值一起显示在屏幕上,并根据这些值在屏幕上的写入位置而改变一些精美的格式。
(我只需要调用 TEXT_SetText(int widget_id, char* text) 来更新我的 GUI 小部件。)
我想要完成的是像这样为 TEXT_SetText() 创建一个“包装器”...
static char text[128], buf[2][32];
#define GET_VAR_AUTO(var_info, i) \
((var_info.getCustomString != NULL && var_info.getCustomString(buf[i])) ? buf[i] : \
(var_info.getRealValue != NULL ? var_info.getRealValue() : 0))
void my_TEXT_SetText(int widget_id, char* format, var_info_t a, var_info_t b){
snprintf(text, sizeof(text), format, GET_VAR_AUTO(a, 0), GET_VAR_AUTO(b, 1));
TEXT_SetText(widget_id, text);
}
...所以调用 my_TEXT_SetText(0, "Regulator is %s at %.1f\260C", var2_info, var1_info);
会在我的盒子里显示一个漂亮的Regulator is Enabled at 15.3°C。
这里真正的优势在于,您可以实时更新文本,只需从“任何地方”定期调用相同的函数(无需“了解任何”变量或其值)。您还可以通过增加 snprintf 参数的数量来简单地扩展同一文本中的变量数量。
问题: GET_VAR_AUTO 宏在语法上不正确,因为它在三元运算符的可能结果中混合了来自buf[i] 的char* 和来自getRealValue() 的float:
错误:条件表达式中的类型不匹配
但是,知道sprintf 是一个可变参数函数,它根据格式字符串(%f、%s、. .. 感谢va_arg() 函数),有没有办法为三元运算符找到一个通用抽象类型,sprintf 会接受它?
我尝试了很多东西,但我无法让 char* 和 float 同时工作。
(不幸的是,我使用的是 C,而不是 C++)
【问题讨论】:
-
真的很难理解你在这里想要做什么,但这听起来像是Generic selection的工作
-
我知道这很难,但我找不到更容易解释的方法。是的,我必须澄清我使用的是 C,而不是 C++... :(
-
@EugeneSh。我不相信仅仅通过泛型选择是可能的...考虑到 OP 希望支持具有任何数量和可能多种类型的函数调用...
-
Motla,IMO,打印对变量或其值“一无所知”的目标与使用
?:的特定方法相关联,并在下面回答了问题。 OTOH,如果您愿意通过另一种方法实现“一无所知”,请考虑_Generic。示例:Formatted print without the need to specify type matching specifiers. -
@Motla 我已经编辑了我的答案,以更好地突出为什么无法在 x86-64 上进行这项工作;)
标签: c types printf conditional-operator mixed