gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 17:15:08 26 4
gpt4 key购买 nike

是否可以使用malloc 来拥有多种类型的数组?

编辑:

目前我有:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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");

如果您知道可能使用的类型,则可以创建 union 或包含 union 的结构,这样您就可以用类型标记它。然后你可以创建一个数组。 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. */

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

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

如果您有另一种方式知道您在每个元素中存储的类型,您可以只使用裸 union ,而无需结构包装它。这更紧凑一些,但每个元素仍将至少与 union 中最大的类型一样大。


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

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

关于c - 指向多种类型的指针数组,C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7798383/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com