c - 如何在没有警告的情况下使结构中的变量等于任何值?(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;
}
解决方案
根据您使用的命名约定,我假设struct var
用于存储键值对,其中值可以是任何类型。不幸的是,C 是静态类型的——如果你声明value
为int
,它只能存储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_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_*
函数。
然而...
您仍然需要一些方法来确定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) );
}
同样,这种方法的美妙之处在于,当您想要添加新的值类型时,您不必修改您的结构或枚举 - 您只需实现复制和指示类型的函数。
推荐阅读
- android - fitSystemWindows 仅适用于 Android 中的背景视图
- javascript - 单击后如何禁用按钮直到第二天
- python - Google Drive Api v3 不允许删除我是共享驱动器组织者的文件
- javascript - 为什么我在尝试使用 vuefire 插件时会出错?
- spring-boot - 如何测试配置文件属性?- Kotlin + Spring Boot + Junit5
- hadoop - 关于 Apache HIVE 的信息
- ruby-on-rails-6 - 任何人都知道为什么 actiontext rich_text_area 会在 Rails 6 中呈现为一个空框?
- react-native - ReactNative 错误:元素类型无效:应为字符串或类/函数,但得到:未定义
- reactjs - next-redux-wrapper TypeError: nextCallback is not a function error in wrapper.getServerSideProps
- java - JavaFX 应用程序在嵌入 gif 的场景在慢速系统中启动之前显示了几分之一秒的空白阶段?