简体   繁体   English

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

[英]Void pointer to struct pointer inside a structure without dereferencing it

Let's imagine I have 3 different types of datasets in 3 different structs: 让我们假设我在3种不同的结构中有3种不同类型的数据集:

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

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

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

Then imagine I want one of those types of data to be assigned to a main struct like this: 然后想象我希望将这些类型的数据之一分配给主结构,如下所示:

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

Say I declare OBJECT* abc = malloc(sizeof(OBJECT)); 假设我声明OBJECT* abc = malloc(sizeof(OBJECT)); and DATATYPE1* dt1 = malloc(sizeof(DATATYPE1)); DATATYPE1* dt1 = malloc(sizeof(DATATYPE1)); Is there a way I could then cast in the code something like this: 有没有办法在代码中强制转换为:

abc->data = dt1;

and then call: 然后打电话:

(abc->data)->a;

without dereferencing the abc->data pointer back to eg DATATYPE1* dp = abc->data and then use dp->a; 没有解除引用abc->data指针回到eg DATATYPE1* dp = abc->data然后使用dp->a;

I assume that the problem is that you want to access the a field of your three DATATYPE S, without knowing which DATATYPE is actually present. 我假设问题是你想要访问三个DATATYPE S的a字段,而不知道实际存在哪个DATATYPE The answer, is yes you can, because the C specification explicitly says that whatever DATATYPE is present, the pointer points at the first member of the structure, and hence can be safely cast to that type. 答案是肯定的,因为C规范明确指出无论DATATYPE存在什么,指针都指向结构的第一个成员,因此可以安全地转换为该类型。

See: Are there any guarantees about C struct order? 请参阅: 对C结构顺序有任何保证吗? and especially: 特别是:

15 Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. 15在结构对象中,非位字段成员和位字段所在的单元具有按声明顺序增加的地址。 A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. 指向适当转换的结构对象的指针指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然。 There may be unnamed padding within a structure object, but not at its beginning. 结构对象中可能存在未命名的填充,但不是在其开头。

Hence, the following code allows you to access a: 因此,以下代码允许您访问:

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

Whether this is good programming practice is another question, that I will not answer. 这是否是良好的编程习惯是另一个问题,我不会回答。

You need to declare everything that you will make reference in your C code. 您需要在C代码中声明要引用的所有内容。 This is the only way to the compiler knows the size and location of the object in that specific address. 这是编译器知道该特定地址中对象的大小和位置的唯一方法。

I think you can use anonymous union blocks and do something like this: 我认为你可以使用匿名联合块并做这样的事情:

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

then use : 然后使用:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM