簡體   English   中英

如何在沒有警告的情況下使結構中的變量等於任何值? (C)

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

所以我有一個簡單的結構,看起來像

struct var {
    char* name;
    int value;
}

而且我不知道如何避免warning: assignment makes integer from [non-int] without a cast [-Wint-conversion] ,我會做很多事情。 我知道我不應該擔心警告,但我真的想擺脫它,那么解決這個問題的最佳方法是什么? 我想做的例子:

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

根據您使用的命名約定,我假設struct var旨在存儲鍵值對,其中值可以是任何類型。 不幸的是, C 是靜態類型的 - 如果您將value聲明為int ,它只能存儲int值。 如果您為其分配一個浮點值,該值將轉換為 integer 並且您將丟失小數部分。 您不能使用它來存儲字符串或任何其他聚合類型。

你基本上有兩個選擇。 您可以將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";

這種方法雖然不涉及動態 memory 以及隨之而來的所有胃灼熱,但卻是一種痛苦。 你必須確保你想要代表的每種類型都有一個聯合成員,如果發生變化,你必須破解類型並重建。 您必須分配給特定的工會成員。

另一種方法是讓value成為一個簡單的void * ,然后動態分配 memory 給它。 雖然這引入了 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" );

其中每個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;
}

這種方法的美妙之處在於,您不必每次想要存儲不同類型的值時都修改struct var類型 - 您只需實現一個新的copy_* function。

然而...

當您以后想要使用它時,您仍然需要一些方法來確定value的類型。 您可以使用上面的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) );
}

同樣,這種方法的美妙之處在於,當您想要添加新的值類型時,您不必修改您的結構或枚舉 - 您只需實現復制和指示類型的函數。

您想要的是在結構內部使用一個union ,其中包含您想要支持的每種類型的字段:

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

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;

使用聯合可能不是您想要的

正如@dbush 所說,工會將解決您眼前的問題。 但是,這就像使用火焰噴射器擦除白板一樣。 它有效,但以后會引起更多問題。

為什么這是代碼對你大喊大叫

C 有一個類型系統。 它可以幫助您檢查您分配給變量的內容是否與變量的類型相同。 int = "hello" + 1真的沒有意義。 您的問題中發生了類似的事情。 int value = "c"是什么意思?

我應該怎么做?

真正的答案是你不會喜歡的。 您可能不應該為數字分配字母。 這就是警告告訴你的。 我們無法真正回答您應該做什么,因為我們需要更多地了解您的代碼。

為什么它是警告而不是錯誤?

使用 ASCII 格式,每個字母都有一個等效的數字。 在更高級的程序中,您可能需要將表示字母的數字分配給具有數字類型的變量。 您通常不想這樣做(所以這是一個警告),但有時您真的想這樣做,並且編譯器知道如果您真的想這樣做(這就是為什么它不是錯誤)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM