微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

TLV 宏扩展引发警告:赋值使指针来自整数而无需强制转换

如何解决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 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?