首页 文章

取消引用指向void数组的指针

提问于
浏览
2

我试图更多地了解C及其神秘的隐藏能力,我试图制作一个包含指向void的指针的示例结构,用作数组 . 编辑:重要说明:这是原始C代码 .

假设我有这个结构 .

typedef struct mystruct {
        unsigned char foo;
        unsigned int max;
        enum data_t type;
        void* data;

    } mystruct;

我希望数据保持无符号字符,无符号短整数和无符号长整数的最大值,data_t枚举包含这3种情况的值 .

enum Grid_t {gi8, gi16, gi32}; //For 8, 16 and 32 bit uints.

然后我有这个函数初始化并分配这个结构之一,并且应该返回一个指向新结构的指针 .

mystruct* new(unsigned char foo, unsigned int bar, long value) {
        mystruct* new;
        new = malloc(sizeof(mystruct)); //Allocate space for the struct.
        assert(new != NULL);
        new->foo = foo;
        new->max = bar;
        int i;
        switch(type){
            case gi8: default:
                new->data = (unsigned char *)calloc(new->max, sizeof(unsigned char));
                assert(new->data != NULL);
                for(i = 0; i < new->max; i++){
                    *((unsigned char*)new->data + i) = (unsigned char)value;
                    //Can I do anything with the format new->data[n]? I can't seem
                    //to use the [] shortcut to point to members in this case!
                }
            break;
        }
        return new;
    }

编译器不返回任何警告,但我对此方法不太确定 . 这是使用指针的合法方式吗?

是否有更好的方式©?

我错过了调用它 . 喜欢mystruct * P; P = new(0,50,1024);

工会很有意思但不是我想要的 . 因为无论如何我都必须单独处理每一个具体案件,铸造似乎和工会一样好 . 我特别希望拥有比32位数组大得多的8位数组,因此联合似乎没有帮助 . 为此,我会把它变成一长串:P

4 回答

  • 0

    type 应该是函数的参数吗? (不要命名此函数或任何变量 new 或任何试图使用它的C程序员将追捕你)

    如果要使用数组索引,可以使用如下临时指针:

    unsigned char *cdata = (unsigned char *)new->data;
    cdata[i] = value;
    

    我真的没有看到你的方法有问题 . 如果你期望一个特定的大小(我认为你给你的名字 gi8 等),我建议包括 stdint.h 并使用typedef uint8_tuint16_tuint32_t .

  • 0

    不,你不能取消引用 void* 指针,它被C语言标准禁止 . 在执行此操作之前,必须将其强制转换为具体的指针类型 .

    作为替代方案,根据您的需要,您还可以在结构中使用 union 而不是 void*

    typedef struct mystruct {
        unsigned char foo;
        unsigned int max;
        enum data_t type;
        union {
            unsigned char *uc;
            unsigned short *us;
            unsigned int *ui;
        } data;
    } mystruct;
    

    在任何给定时间, data.ucdata.usdata.ui 中只有一个有效,因为它们都占用内存中的相同空间 . 然后,您可以使用适当的成员来获取数据数组,而无需从 void* 强制转换 .

  • 2

    关于什么

    typedef struct mystruct 
    {
        unsigned char foo;
        unsigned int max;
        enum data_t type;
        union
        {
            unsigned char *chars;
            unsigned short *shortints;
            unsigned long *longints; 
        };
    } mystruct;
    

    这样,根本不需要施放 . 只需使用 data_t 来确定您要访问的指针 .

  • 1

    指针仅仅是存储空间中的地址 . 您可以根据需要选择解释它 . 有关如何以多种方式解释相同内存位置的详细信息,请查看 union .

    指针类型之间的转换在C和C中很常见,并且使用void *意味着您不希望用户意外取消引用(取消引用void *将导致错误,但在转换为int *时取消引用相同的指针)

相关问题