如何初始化一个可接受任何类型的变量?
并且,如何将该类型转换回我想要的类型?(类型转换)
谢谢。
定义一个可以保存多种类型值的变量的方法是使用联合:
union uu {
int i;
float f;
char c;
char *s;
} x;
x.i是一个整数,x.s是一个字符指针等等。x的大小是成员类型中最大的。
不幸的是,记住变量的类型的唯一方法是将其存储在其他地方。常见的解决方案是使用这样的结构:
struct ss {
int type;
union {
int i;
float f;
char c;
char *s;
} val;
} x;
然后进行如下操作:
#define FLOAT 1
#define INT 2
....
x.val.i = 12;
x.type = INT;
....
if (x.type = INT) printf("%d\n",x.val.i);
....
真的很丑陋。
还有其他可能性可以通过宏处理器来使其更加美观,但本质是你必须事先知道联合中存储的值类型并访问正确的字段。
struct { void * data; enum Type tag }
并定义一个enum Type { int, char*,... etc }
void *
是指向没有类型的数据的指针,因此您可以使用它来存储包含要存储的数据的内存块。void *
即可。::VariantInit(&myVariant);
开始。 - Andomar你有两个选择:
void* foo;
它可以指向任何类型的数据,或者:
union my_types {
int* i;
char* s;
double* d;
bool* b;
void* other;
}
这个功能使您可以进行“自动”指针转换(您可以将类型为“my_types”的变量引用,就像它是上述任何一种类型一样)。有关union的更多信息,请参见此链接。
以上两种选项都不是很好 - 考虑使用C ++来实现您想要做的事情。
void *
。你的解决方案将需要使用指向void的指针。 指向void的指针可以保存任何对象类型(不包括函数),并且可以在不丢失信息的情况下转换回来。
最好使用“父结构体”,以便您知道指针所指向的对象类型:
enum MyType { INTEGER, DOUBLE_STAR };
struct anytype {
enum MyType mytype;
size_t mysize;
void *myaddress;
};
然后
struct anytype any_1, any_2;
int num_chars;
double array[100];
any_1.mytype = INTEGER;
any_1.myaddress = &num_chars;
any_1.mysize = sizeof num_chars;
any_2.mytype = DOUBLE_STAR;
any_2.myaddress = array;
any_2.size = sizeof array;
还有,要与之一起工作
foo(any_1);
foo(any_2);
其中foo
被定义为
void foo(struct anytype thing) {
if (thing.mytype == INTEGER) {
int *x = thing.myaddress;
printf("the integer is %d\n", *x);
}
if (thing.mytype == DOUBLE_STAR) {
size_t k;
double *x = thing.myaddress;
double sum = 0;
for (k = 0; k < thing.mysize; k++) {
sum += thing.myaddress[k];
}
printf("sum of array: %f\n", sum);
}
}
代码未经测试
使用 void *
?
你可以将其强制转换成任何你想要的类型,当然前提是你必须自己进行检查。
enum _myType { CHAR, INT, FLOAT, ... }myType;
struct MyNewType
{
void * val;
myType type;
}
然后,您可以将类型为MyNewType的元素传递给您的函数。检查类型并执行适当的转换。
您可以使用 void *
指针来接受几乎任何指针。关键在于将其强制转换回所需类型:您必须在某个地方存储有关指针的类型信息。
您可以使用 struct
来存储 void *
指针和类型信息,并将其添加到数据结构中。主要问题在于类型信息本身;C 不包含任何类型反射,因此您可能需要创建一组类型枚举或存储描述该类型的字符串。然后,您必须通过查询类型信息来强制 struct
的用户将 void *
转换回原始类型。
这并不是理想的情况。一个更好的解决方案可能是转移到 C++ 或甚至 C# 或 Java。
C语言提供了联合体,可能适合您的需求。在编译之前,您需要定义所有类型,但是同一变量可以指向联合体中包含的所有类型。