指针数组多种类型,C [英] Array of POINTERS to Multiple Types, C

查看:146
本文介绍了指针数组多种类型,C的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有可能通过使用的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]);
}

但它是凌乱。其他的方法?

But it's messy. Other ways?

编辑:清理它有点

推荐答案

您不能拥有不同类型的数组,准确。但可以达到类似的效果(对于某些目的至少)在许多不同的方式。

You can't have an array of different types, exactly. But you can achieve a similar effect (for some purposes at least) in a number of different ways.

如果你只是想不同类型的几个值打包在一起,但数量和类型的值不改变,你只需要一个结构键,可以访问它们按名称:

If you just want a few values of different types packaged together, but the number and types of values don't change, you just need a struct and can access them by name:

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


如果你知道你可以使用什么类型的,你可以创建一个联盟,或包含联合的结构,所以你可以用类型标记它。然后,您可以创建这些数组。在键入成员可以让你检查,看看你存储在每个数组元素后面的东西。


If you know what types you might use, you can create a union, or a struct containing a union so you can tag it with the type. You can then create an array of those. The type member lets you check to see what you stored in each array element later.

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. */

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

This approach may waste space because:


  • 每个元素都有一个额外的价值,以保持其持有的数据类型
  • 跟踪
  • 的结构可能有其成员之间微胖

  • 在工会的类型可以是不同的大小,在这种情况下,工会将成为最大的类型为大

如果你还不认识你已经存储在每个元素是什么类型的另一种方式,你可以只使用裸工会没有结构包装它。这是一个小更紧凑,但每个元素依然会至少在工会最大的类型一样大。

If you have another way of knowing what type you've stored in each element, you can use just the bare union without the struct wrapping it. This is a little more compact, but each element will still be at least as large as the largest type in the union.

您还可以创建无效* 值的数组。如果你这样做,你就必须以某种方式分配的项目,并指定其地址数组元素。然后,你需要将它们转换为相应的指针类型访问项目。 C不提供任何运行时类型信息,所以没有办法找出什么类型的数据从指针本身的每个元素点 - 你必须跟踪自己找。这种方法是很多比别人更紧凑,当你存储的类型有很大及其大小相差很多,因为每个单独从阵列中分配的,并且可以只给出需要的那种类型的空间。对于简单的类型,你真的不获得对利用共用东西。

You can also create an array of void * values. If you do this, you'll have to allocate the items somehow and assign their addresses to the array elements. Then you'll need to cast them to the appropriate pointer type to access the items. C doesn't provide any runtime type information, so there's no way to find out what type of data each element points at from the pointer itself -- you must keep track of that on your own. This approach is a lot more compact than the others when the types you're storing are large and their sizes vary a lot, since each is allocated separately from the array and can be given only the space needed for that type. For simple types, you don't really gain anything over using a 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);

如果您需要跟踪该类型的阵列中,也可以使用结构来存储类型的指针,类似与工会前面的例子一起。这,同样,当所存储的类型有很大的超额很多大小只有真正有用的。

If you need to keep track of the type in the array, you can also use a struct to store the type along with the pointer, similar to the earlier example with the union. This, again, is only really useful when the types being stored are large and vary a lot in size.

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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆