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

时间:2011-08-04 19:18:12

标签: c arrays pointers void dereference

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

假设我有这个结构。

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

    } mystruct;

我希望数据保存无符号字符,无符号短整数和无符号长整数的 max ,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 :(得分:2)

不,你不能取消引用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*转换。

答案 1 :(得分:1)

怎么样?
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来确定您要访问的指针。

答案 2 :(得分:0)

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

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

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

我的方法确实没有问题。如果您期望某个特定尺寸(我认为您确实给出了名称gi8等),我建议您使用stdint.h并使用typedef uint8_tuint16_t和{ {1}}。

答案 3 :(得分:0)

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

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