在C语言中使用异构数组

在C语言中使用异构数组,c,C,我希望使用具有多种类型的数组-字符串和数字int。以下是我到目前为止得到的: int main(int argc, char *argv[]) { int number = 2; void * array[] = {"helo", &number, "watkins"}; int array_len = sizeof(array)/sizeof(array[0]) for (int i=0; i<array_len; i++) {

我希望使用具有多种类型的数组-字符串和数字int。以下是我到目前为止得到的:

int main(int argc, char *argv[]) {

    int number = 2;
    void * array[] = {"helo", &number, "watkins"};
    int array_len = sizeof(array)/sizeof(array[0])

    for (int i=0; i<array_len; i++) {
        void *value = array[i];

        // how to do this in C?
        if (type(value) == char)
            printf("The string is: %s", value);
        else
            printf("The number is: %d", value);

    }

}

如何在C语言中测试类型或执行等效操作?

在C语言级别上,此功能不存在。如果你想要这样的东西,你必须自己创造。因此,数组元素的类型必须可以包含任何一种类型的对象,例如结构或联合。此外,您的代码必须跟踪哪种类型是哪种类型-语言不会为您这样做

因此,一种方法如下所示:

#include <stdio.h>
#include <stdlib.h>

enum my_type { IS_STRING, IS_INTEGER };

struct my_multitype {
    enum my_type t;
    union {
        char *s;
        int n;
    } u;
};

int main(int argc, char *argv[]) {

    struct my_multitype array[] =
        {
         { IS_STRING, { .s = "helo" } },
         { IS_INTEGER, { .n = 2 } },
         { IS_STRING, { .s = "watkins" } }
        };

    int array_len = sizeof(array)/sizeof(array[0]);

    for (int i=0; i<array_len; i++) {
        switch (array[i].t) {
        case IS_STRING:
            printf("The string is: %s\n", array[i].u.s);
            break;
        case IS_INTEGER:
            printf("The number is: %d\n", array[i].u.n);
            break;
        default:
            printf("Something is horribly wrong\n");
            abort();
            break;
        }
    }
}
注意,在每种情况下,我们都使用初始化正确的联合成员


您也可以尝试使用void*,但是您必须将类型信息保存在单独的数组或其他东西中,这很尴尬。初始化这样的数组也很尴尬,正如你在整数中看到的那样,你必须引入一个辅助变量。

我喜欢内特的答案,所以不要改变你的选择,但它有一个微妙的变化,即使用匿名联合,这将允许您直接引用联合的成员,而无需使用联合标记引用成员

这是在年的C11标准中引入的。它只是提供了一些语法上的简写。例如,在结构中使用匿名联合,例如

typedef struct {    /* struct containing tag and union between int/char[] */
    int tag;
    union {                 /* anonymous union allow you to refer  */ 
        char str[MAXC];     /* to members as members of the struct */
        int number;
    };
} mytype;
...
    mytype array[] = {{ISSTR, {"helo"}}, {ISINT, {{2}}}, {ISSTR, {"watkins"}}};
您与工会成员的联系方式如下:

            printf ("The string is: %s\n", array[i].str);
#include <stdio.h>

#define MAXC 16     /* if you need a constant, #define one (or more) */

enum { ISSTR, ISINT };  /* enum can provide global constants as well */

typedef struct {    /* struct containing tag and union between int/char[] */
    int tag;
    union {                 /* anonymous union allow you to refer  */ 
        char str[MAXC];     /* to members as members of the struct */
        int number;
    };
} mytype;

int main (void) {

    mytype array[] = {{ISSTR, {"helo"}}, {ISINT, {{2}}}, {ISSTR, {"watkins"}}};
    int array_len = sizeof array/sizeof *array;

    for (int i=0; i<array_len; i++) {
        // how to do this in C?
        if (array[i].tag == ISSTR)      /* if tag ISSTR element is string */
            printf ("The string is: %s\n", array[i].str);
        else if (array[i].tag == ISINT) /* if ISINT, element holds an int */
            printf ("The number is: %d\n", array[i].number);
        else
            fputs ("As Nate put it, things are horribly wrong...\n", stderr);
    }
}

数组[i]和str或number之间没有联合标记

总之,你的例子是:

            printf ("The string is: %s\n", array[i].str);
#include <stdio.h>

#define MAXC 16     /* if you need a constant, #define one (or more) */

enum { ISSTR, ISINT };  /* enum can provide global constants as well */

typedef struct {    /* struct containing tag and union between int/char[] */
    int tag;
    union {                 /* anonymous union allow you to refer  */ 
        char str[MAXC];     /* to members as members of the struct */
        int number;
    };
} mytype;

int main (void) {

    mytype array[] = {{ISSTR, {"helo"}}, {ISINT, {{2}}}, {ISSTR, {"watkins"}}};
    int array_len = sizeof array/sizeof *array;

    for (int i=0; i<array_len; i++) {
        // how to do this in C?
        if (array[i].tag == ISSTR)      /* if tag ISSTR element is string */
            printf ("The string is: %s\n", array[i].str);
        else if (array[i].tag == ISINT) /* if ISINT, element holds an int */
            printf ("The number is: %d\n", array[i].number);
        else
            fputs ("As Nate put it, things are horribly wrong...\n", stderr);
    }
}

请记住,这是C11引入的,在C99中,您将找不到匿名结构或匿名联合,尽管某些编译器提供了作为扩展的

您可以创建一个联合数组。我想您想创建一个类似于Python或JavaScript的数组吗?@AbdulRehman是的,类似于此。您可以创建一个结构变量数组{字符类型;void*数据;}当你阅读它的时候,你会检查每个元素的类型,以知道如何处理它各自的数据。用一种更简单的方式来做是不可能的,因为C的设计不支持这一点,所以C的语法也不支持。在C中,数组是由单一类型的对象组成的。现在数组可以是一个结构数组。但是,你不能这样做e一个void*类型的数组,因为该类型没有提供关于您所声明内容的完整信息。是的,这正是我应该如何处理它的,但是您在标记的枚举中做得更好,我只使用了一个int标记;作为一个标志。如果没有指定的初始值设定项,您可以执行{{1,{hello},{0,{2}},…..此外,您还可以删除命名联合体的“u”,只需引用,例如数组[i].s和数组[i].n。