在结构内部对结构指针进行Void指针而不取消引用它

时间:2017-01-31 17:34:03

标签: c pointers struct void-pointers

让我们想象一下,我在3种不同的结构中有3种不同类型的数据集:

typedef struct
{
    int a;
    //...
}DATATYPE1;

typedef struct
{
    int a;
    //...
}DATATYPE2;

typedef struct
{
    int a;
    //...
}DATATYPE3;

然后想象我希望将这些类型的数据中的一种分配给这样的主结构:

typedef struct
{
    int b;
    void* data;
    //...
}OBJECT;

说我宣布OBJECT* abc = malloc(sizeof(OBJECT));DATATYPE1* dt1 = malloc(sizeof(DATATYPE1)); 有没有办法可以在代码中强制转换:

abc->data = dt1;

然后致电:

(abc->data)->a;

不取消引用abc->data指针返回e.g. DATATYPE1* dp = abc->data,然后使用dp->a;

2 个答案:

答案 0 :(得分:3)

我认为问题是您想要访问三个a S的DATATYPE字段,而不知道实际存在哪个DATATYPE。答案是肯定的,因为C规范明确规定无论DATATYPE存在什么,指针都指向结构的第一个成员,因此可以安全地转换为该类型。

请参阅:Are there any guarantees about C struct order?,尤其是:

  

15在结构对象中,非位字段成员和单位   其中位字段驻留的地址按顺序增加   他们被宣布。适当地指向结构对象的指针   转换后,指向其初始成员(或者如果该成员是   位字段,然后到它所在的单元,反之亦然。   结构对象中可能有未命名的填充,但不在其中   开始。

因此,以下代码允许您访问:

OBJECT* abc = malloc(sizeof(OBJECT));
abc->data = malloc(sizeof(DATATYPE1));
int* pointerToA = (int*) abc->data;

这是否是良好的编程习惯是另一个问题,我不会回答。

答案 1 :(得分:0)

您需要声明您将在C代码中引用的所有内容。这是编译器知道该特定地址中对象的大小和位置的唯一方法。

我认为您可以使用匿名联合块并执行以下操作:

typedef struct
{
    int b;
    union {
       void* data;
       DATATYPE1 *dt1;
       DATATYPE2 *dt2:
       DATATYPE3 *dt3;
    };    
} OBJECT;

然后使用:

OBJECT* abc = (OBJECT*)malloc(sizeof(OBJECT));
DATATYPE1* dt1 = (DATATYPE1*)malloc(sizeof(DATATYPE1));
abc->data = (void *)dt1;
int val = abc->dt1->a;