简体   繁体   English

如何在没有警告的情况下使结构中的变量等于任何值? (C)

[英]How do I make a variable in a struct equal to any value without a warning? (C)

So I have a simple struct that looks like所以我有一个简单的结构,看起来像

struct var {
    char* name;
    int value;
}

and I don't know how to avoid warning: assignment makes integer from [non-int] without a cast [-Wint-conversion] when I try to make value a non-integer, which I'll be doing a lot.而且我不知道如何避免warning: assignment makes integer from [non-int] without a cast [-Wint-conversion] ,我会做很多事情。 I know I shouldn't worry about a warning, but I really want to get rid of it, so what's the best way to fix this?我知道我不应该担心警告,但我真的想摆脱它,那么解决这个问题的最佳方法是什么? Example of what I want to do:我想做的例子:

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

Based on the naming conventions you're using, I'm assuming struct var is meant to store key-value pairs, where the value can be any type.根据您使用的命名约定,我假设struct var旨在存储键值对,其中值可以是任何类型。 Unfortunately, C is statically typed - if you declare value as an int , it can only store int values.不幸的是, C 是静态类型的 - 如果您将value声明为int ,它只能存储int值。 If you assign a floating-point value to it, that value will be converted to an integer and you will lose the fractional portion.如果您为其分配一个浮点值,该值将转换为 integer 并且您将丢失小数部分。 You can't use it to store a string or any other aggregate type.您不能使用它来存储字符串或任何其他聚合类型。

You basically have two options.你基本上有两个选择。 You can make value a union of different types:您可以将value设为不同类型的联合

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

and then you can store different types to different members of the union:然后您可以将不同的类型存储到联合的不同成员:

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";

This approach, while not involving dynamic memory and all the heartburn that comes with it, is a pain.这种方法虽然不涉及动态 memory 以及随之而来的所有胃灼热,但却是一种痛苦。 You have to make sure you have a union member for every type you want to represent, and if that changes you have to hack the type and rebuild.你必须确保你想要代表的每种类型都有一个联合成员,如果发生变化,你必须破解类型并重建。 You have to assign to the specific union member.您必须分配给特定的工会成员。

Another approach is to make value a simple void * , and then dynamically allocate and assign memory to it.另一种方法是让value成为一个简单的void * ,然后动态分配 memory 给它。 While this introduces memory management headaches, it's more flexible and easier to abstract.虽然这引入了 memory 管理难题,但它更灵活且更易于抽象。

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" );

where each of copy_int , copy_float , and copy_string are functions that abstract away the malloc calls and assignments:其中每个copy_intcopy_floatcopy_string都是抽象出malloc调用和分配的函数:

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;
}

The beauty of this method is that you don't have to hack your struct var type every time you want to store a different type of value - you only have to implement a new copy_* function.这种方法的美妙之处在于,您不必每次想要存储不同类型的值时都修改struct var类型 - 您只需实现一个新的copy_* function。

However...然而...

You still need some way to determine what the type of value is when you want to use it later on.当您以后想要使用它时,您仍然需要一些方法来确定value的类型。 You can either the enum method above to explicitly tag it, or you can add a function pointer member and create functions to return information about the type, like so:您可以使用上面的enum方法对其进行显式标记,也可以添加 function 指针成员并创建函数以返回有关类型的信息,如下所示:

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) );
}

Again, the beauty of this approach is you don't have to hack your struct or the enum when you want to add new value types - you only have to implement the functions to copy and indicate type.同样,这种方法的美妙之处在于,当您想要添加新的值类型时,您不必修改您的结构或枚举 - 您只需实现复制和指示类型的函数。

What you want is to use a union inside of the struct with fields for each type you want to support:您想要的是在结构内部使用一个union ,其中包含您想要支持的每种类型的字段:

struct var {
    char* name;
    char type;
    union {
        int i;
        char c;
        char *s;
        float f;
        double d;
    } value;
};

The type field can be used to determine which field of the union is active: type字段可用于确定 union 的哪个字段处于活动状态:

struct var a[100];
a[0].name = "a";
a[0].type = 's';
a[0].value.s = "c";
a[1].name = "b";
a[0].type = 'i';
a[1].value.i = 0;

Using a union is probably not what you want使用联合可能不是您想要的

As @dbush stated, a union will fix your immediate problem.正如@dbush 所说,工会将解决您眼前的问题。 However, this is like using a flamethrower to erase a whiteboard.但是,这就像使用火焰喷射器擦除白板一样。 It works, but it will cause more problems later on.它有效,但以后会引起更多问题。

Why this is the code yelling at you为什么这是代码对你大喊大叫

C has a type system. C 有一个类型系统。 It helps you check if what you're assigning to the variable has the same type as what the variable is.它可以帮助您检查您分配给变量的内容是否与变量的类型相同。 It doesn't really make sense to say int = "hello" + 1 .int = "hello" + 1真的没有意义。 Something similar is happening in your question.您的问题中发生了类似的事情。 What does int value = "c" mean? int value = "c"是什么意思?

What should I do instead?我应该怎么做?

The real answer is one you won't like.真正的答案是你不会喜欢的。 You probably shouldn't assign a letter to a number.您可能不应该为数字分配字母。 This is what the warning is telling you.这就是警告告诉你的。 We can't really answer what you should be doing as we would need to have more knowledge of your code.我们无法真正回答您应该做什么,因为我们需要更多地了解您的代码。

Why is it a warning and not an error?为什么它是警告而不是错误?

Using the ASCII format, each letter has an equivalent number.使用 ASCII 格式,每个字母都有一个等效的数字。 In more advanced programs, you might need to assign the number representing the letter into a variable with a numeric type.在更高级的程序中,您可能需要将表示字母的数字分配给具有数字类型的变量。 You usually don't want to do this (so it's a warning) but sometimes you really want to do that, and the compiler knows how to do it if you really want to (which is why it is not an error).您通常不想这样做(所以这是一个警告),但有时您真的想这样做,并且编译器知道如果您真的想这样做(这就是为什么它不是错误)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM