指向多种类型的指针数组,C

使用malloc可以有多个类型的数组吗?

编辑:

目前我有:

 #include  #include  #include  #define int(x) *((int *) x) int main() { void *a[10]; a[0] = malloc(sizeof(int)); int(a[0]) = 4; char *b = "yola."; a[1] = malloc(strlen(b)*sizeof(char)); a[1] = b; printf("%d\n", int(a[0])); printf("%s\n", a[1]); } 

但它很乱。 其他方法?

编辑:清理了一下。

确切地说,您不能拥有不同类型的数组。 但是你可以通过多种不同的方式达到类似的效果(至少出于某些目的)。

如果您只是希望将不同类型的一些值打包在一起,但值的数量和类型不会更改,您只需要一个struct并可以按名称访问它们:

 struct s_item { int number; char str[100]; } item; item.number = 5; strcpy(item.str,"String less than 100 chars"); 

如果您知道可能使用的类型,则可以创建一个联合或包含联合的结构,以便您可以使用该类型对其进行标记。 然后,您可以创建这些数组。 type成员允许您稍后检查以查看存储在每个数组元素中的内容。

 enum ElementType { et_str, et_int, et_dbl }; struct Element { ElementType type; union { char *str; int i; double d; } }; struct Element *arr = malloc(sizeof(struct Element) * 3); arr[0].type = et_str; arr[0].str = strdup("String value"); /* remember to free arr[0].str */ arr[1].type = et_int; arr[1].i = 5; arr[2].type = et_dbl; arr[2].d = 27.3; /* access the values.. */ for (int i = 0; i < 3; i++) { switch(arr[i].type) { case et_str: printf("String: %s\n",arr[i].str); break; case et_int: printf("Integer: %d\n",arr[i].i); break; case et_dbl: printf("Double: %f\n",arr[i].d); break; } } /* The strings are dynamically allocated, so free the strings */ for (int i = 0; i < 3; i++) if (arr[0].type == et_str) free(arr[0].str); /* free the malloc'ed array */ free(arr); /* etc., etc. */ 

这种方法可能会浪费空间,因为

  • 每个元素都有一个额外的值来跟踪它所拥有的数据类型
  • 结构可以在其成员之间具有额外的填充
  • 联合中的类型可以是不同的大小,在这种情况下,联合将与最大类型一样大

如果你有另一种方法可以知道你在每个元素中存储了什么类型,你可以只使用裸结合而不用结构包装它。 这个更紧凑,但每个元素仍然至少与联合中最大的类型一样大。


您还可以创建一个void *值数组。 如果这样做,您将不得不以某种方式分配项目并将其地址分配给数组元素。 然后,您需要将它们转换为适当的指针类型以访问项目。 C不提供任何运行时类型信息,因此无法找出每个元素从指针本身指向的数据类型 - 您必须自己跟踪它。 当您存储的类型很大并且它们的大小变化很大时,这种方法比其他方法紧凑得多,因为每个类型都与数组分开分配,并且只能给出该类型所需的空间。 对于简单类型,您实际上并没有使用联合。

 void **arr = malloc(3 * sizeof(void *)); arr[0] = strdup("Some string"); /* is a pointer already */ arr[1] = malloc(sizeof(int)); *((int *)(arr[1])) = 5; arr[2] = malloc(sizeof(double)); *((double *)(arr[2])) = 27.3; /* access the values.. */ printf( "String: %s\n", (char *)(arr[0]) ); printf( "Integer: %d\n", *((int *)(arr[1])) ); printf( "Double: %f\n", *((double *)(arr[2])) ); /* ALL values were dynamically allocated, so we free every one */ for (int i = 0; i < 3; i++) free(arr[i]); /* free the malloc'ed array */ free(arr); 

如果需要跟踪数组中的类型,还可以使用结构将类型与指针一起存储,类似于前面的union示例。 同样,当存储的类型很大并且大小变化很大时,这才真正有用。

 enum ElementType { et_str, et_int, et_dbl }; struct Element { ElementType type; void *data; }; struct Element *arr = malloc(sizeof(struct Element) * 3); arr[0].type = et_str; arr[0].data = strdup("String value"); arr[1].type = et_int; arr[1].data = malloc(sizeof(int)); *((int *)(arr[1].data)) = 5; arr[2].type = et_dbl; arr[2].data = malloc(sizeof(double)); *((double *)(arr[2].data)) = 27.3; /* access the values.. */ for (int i = 0; i < 3; i++) { switch(arr[i].type) { case et_str: printf( "String: %s\n", (char *)(arr[0].data) ); break; case et_int: printf( "Integer: %d\n", *((int *)(arr[1].data)) ); break; case et_dbl: printf( "Double: %f\n", *((double *)(arr[2].data)) ); break; } } /* again, ALL data was dynamically allocated, so free each item's data */ for (int i = 0; i < 3; i++) free(arr[i].data); /* then free the malloc'ed array */ free(arr); 

不,所有元素都必须属于同一类型。 你可能会逃脱一系列结构。

 struct mixed { enum { INTEGER, STRING, } type; union { int num; char *str; } value; }; struct mixed v[10]; v[0].type = INTEGER; v[0].value.num = 10; 

我自己永远不会做这样的事情(看起来很乱)。 但是你的array-of-void *方法是类似的:你必须在某个地方存储类型的信息。

您可以轻松拥有指向不同类型的指针数组。 当然,为了使它非常有用,您需要有一些方法来记录或确定每个元素当前引用的类型。

 #include  #include  #include  int main() { // This implicitly allocates memory to store 10 pointers void *a[10]; // The first element will be a pointer to an int // Allocate the memory it points to, then assign it a value. a[0] = malloc(sizeof(int)); *( (int *)a[0] ) = 4; // The second element will be a pointer to char; for simplicity, // I'm hardcoding the length of the string + 1 for the null byte. a[1] = malloc( 6*sizeof(char) ); strncpy( a[1], "hello", 5 ); printf( "%d\n", *( (int *)a[0] ) ); printf( "%s\n", a[1] ); } 

我不确定你想要实现什么,但有两种可能性:

1 – 你实际上并不想要一个数组而是一个结构:

 struct { int number; char *string; } a; 

在这种情况下,您可以将数字作为a.string访问,将字符串作为a.string

2 – 您需要一个变体类型的数组。 在C中,您可以使用变量类型的联合(最好是标记):

 struct Variant { int type; union { int number; char *string; } } 

然后你可以编码你的类型,数字为0,字符串为1。 当然,对类型使用枚举而不是整数将是更好的方法。

这是因为你试图将一个值存储到一个期望指针的插槽中。 请尝试以下操作(为简洁起见,省略了错误检查)

 int* pIntTemp = malloc(sizeof(int)); *pIntTemp = 4; a[0] = pIntTemp;