如何解决TLV 宏扩展引发警告:赋值使指针来自整数而无需强制转换
我的 TLV 结构可以保存字符串或整数。我正在尝试创建一个处理它们的宏。
下面的示例按预期运行,但编译时出现来自 MACRO 扩展的警告。我知道预编译器无法知道我将在运行时分配什么类型的值,这就是为什么我认为它会引发警告。
如何修复这个小代码片段,使其不产生编译警告?
FWIW,我可以通过不使用 MACRO 来解决这个问题,但如果可能的话,我更愿意使用它。
$ gcc -o simple{,.c} && ./simple
simple.c: In function ‘main’:
simple.c:25:21: warning: assignment makes pointer from integer without a cast [enabled by default]
tlv.value_str = (val); \
^
simple.c:38:3: note: in expansion of macro ‘TLV2STR_MACRO’
TLV2STR_MACRO(string,TYPE_INT,11);
^
simple.c:28:21: warning: assignment makes integer from pointer without a cast [enabled by default]
tlv.value_int = (val); \
^
simple.c:41:3: note: in expansion of macro ‘TLV2STR_MACRO’
TLV2STR_MACRO(string,TYPE_STRING,"ELEVEN");
^
-----------------------------
INT : 11
STRING: ELEVEN
-----------------------------
#include <stdio.h>
typedef struct _tlv_s {
int type;
size_t length;
union _value {
int value_int;
char *value_str;
} value_u;
} tlv_t;
#define value_int value_u.value_int
#define value_str value_u.value_str
#define TYPE_STRING 0
#define TYPE_INT 1
#define TLV2STR_MACRO(s,t,val) { \
tlv_t tlv; \
tlv.type = (t); \
if (t == TYPE_STRING) { \
tlv.value_str = (val); \
sprintf(s,"STRING: %s",tlv.value_str); \
} else { \
tlv.value_int = (val); \
sprintf(s,"INT : %d",tlv.value_int); \
} \
}
int main(int argc,char *argv[])
{
char string[128];
printf("-----------------------------\n");
TLV2STR_MACRO(string,11);
printf("%s\n",string);
TLV2STR_MACRO(string,"ELEVEN");
printf("%s\n",string);
printf("-----------------------------\n");
}
解决方法
如何修复这个小代码片段,使其不产生编译警告?
您可以添加显式强制转换。
tlv.value_str = (char*)(val); \
tlv.value_int = (int)(val); \
对于您的 FWIW,这样的宏不会扩展,虽然为具有两种类型和一种用例的玩具示例编写速度很快,但当更多时它会变得痛苦和不可读。将 virtual table 与调度函数一起使用,保持代码可读性,不要使用宏。我建议删除令人困惑的定义 #define value_int value_u.value_int
并将您的符号保留在一个命名空间 tlv_*
中。不要以 unreadable big switches 结尾,这似乎是您的代码所追求的。更喜欢使用 snprintf
而不是 sprintf
。
我相信(很高兴得到其他证明)不可能按照我的意图传递值,将它们任意转换为字符串或整数。
相反,将指针传递给值并转换指针是正确的方法。 (顺便说一句,如果这真的是一个 TLV 实现,它可以处理任何类型的结构,但这只是一个用来演示传递值问题的小应用。
请注意,我修改了宏以接受指向该值的指针。
#include <stdio.h>
typedef struct _tlv_s {
int type;
size_t length;
union _value {
int value_int;
char *value_str;
} value_u;
} tlv_t;
#define value_int value_u.value_int
#define value_str value_u.value_str
#define TYPE_STRING 0
#define TYPE_INT 1
#define TLV2STR_MACRO(s,t,valp) { \
tlv_t tlv; \
tlv.type = (t); \
if (t == TYPE_STRING) { \
tlv.value_str = (char *)(valp); \
sprintf(s,"STRING: %s",tlv.value_str); \
} else { \
tlv.value_int = *(int *)(valp); \
sprintf(s,"INT : %d",tlv.value_int); \
} \
}
int main(int argc,char *argv[])
{
char string[128];
int val_int = 11;
printf("-----------------------------\n");
TLV2STR_MACRO(string,TYPE_INT,&val_int);
printf("%s\n",string);
TLV2STR_MACRO(string,TYPE_STRING,"ELEVEN");
printf("%s\n",string);
printf("-----------------------------\n");
}
以及编译和运行的输出....
$ gcc -o simple{,.c} && ./simple asdf
-----------------------------
INT : 11
STRING: ELEVEN
-----------------------------
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。