首页 > 解决方案 > 如何在没有警告的情况下使结构中的变量等于任何值?(C)

问题描述

所以我有一个简单的结构,看起来像

struct var {
    char* name;
    int value;
}

warning: assignment makes integer from [non-int] without a cast [-Wint-conversion]当我尝试将 value 设为非整数时,我不知道如何避免,我会做很多事情。我知道我不应该担心警告,但我真的想摆脱它,那么解决这个问题的最佳方法是什么?我想做的例子:

int main() {
    struct var a[100];
    a[0].name = "a";
    a[0].value = "c";
    a[1].name = "b";
    a[1].value = 0;
}

标签: cstruct

解决方案


根据您使用的命名约定,我假设struct var用于存储键值对,其中值可以是任何类型。不幸的是,C 是静态类型的——如果你声明valueint,它只能存储int值。如果您为其分配一个浮点值,该值将转换为整数,您将丢失小数部分。您不能使用它来存储字符串或任何其他聚合类型。

你基本上有两个选择。您可以创建不同类型value联合

enum var_type { INTEGER, FLOATING, STRING };
struct var
{
  char *name;
  enum var_type type;
  union {
    int i;
    double f;
    char *s;
  } value;
};

然后您可以将不同的类型存储到联合的不同成员:

struct var v[3];
v[0].name = "foo";
v[0].type = INTEGER;
v[0].value.i = 1;

v[1].name = "bar";
v[1].type = FLOATING;
v[1].value.f = 3.14;

v[2].name = "bletch";
v[2].type = STRING;
v[2].value.s = "this is a test";

这种方法虽然不涉及动态记忆和随之而来的所有胃灼热,但却是一种痛苦。你必须确保你想要代表的每种类型都有一个联合成员,如果发生变化,你必须破解类型并重建。您必须分配给特定的工会成员。

另一种方法是制作value一个简单void *的 ,然后为它动态分配和分配内存。虽然这引入了内存管理问题,但它更灵活且更易于抽象。

struct var {
  char *name;
  void *value;
};

struct var v[3];
v[0].name = "foo";
v[0].value = copy_int( 1 );

v[1].name = "bar";
v[1].value = copy_float( 3.14 );

v[2].name = "bletch";
v[2].value = copy_string( "this is a test" );

其中 、 和 中的每一个copy_int都是copy_float抽象copy_stringmalloc调用和赋值的函数:

void *copy_int( int arg )
{
  int *mem = malloc( sizeof *mem );
  if ( mem )
    *mem = arg;
  return mem;
}

void *copy_float( double arg )
{
  double *mem = malloc( sizeof *mem );
  if ( mem )
    *mem = arg;
  return mem;
}

void *copy_string( const char *str )
{
  char *mem = malloc( sizeof *mem * (strlen( str ) + 1 ));
  if ( mem )
    strcpy( mem, str );
  return mem;
}

这种方法的美妙之处在于,您不必struct var每次想要存储不同类型的值时都修改您的类型——您只需实现一个新copy_*函数。

然而...

您仍然需要一些方法来确定value您以后想要使用它时的类型。您可以使用上述enum方法对其进行显式标记,也可以添加函数指针成员并创建函数以返回有关类型的信息,如下所示:

struct var {
  char *name;
  void *value;
  char *(*type)( void );
};

char *int_type( void ) { return "int"; }
char *double_type( void ) { return "double"; }
char *string_type( void ) { return "string"; }
...
struct var v[3];
v[0].name = "foo";
v[0].type = int_type;
v[0].value = copy_int( 1 );
...
if ( strcmp( v[0].type(), "int" ) )
{
  printf( "%s = %d\n", v[0].name, *((int *) v[0].value) );
}

同样,这种方法的美妙之处在于,当您想要添加新的值类型时,您不必修改您的结构或枚举 - 您只需实现复制和指示类型的函数。


推荐阅读