指向结构内部结构指针的空指针而不取消引用它
Void pointer to struct pointer inside a structure without dereferencing it
假设我在 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;
您需要声明您将在 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;
我假设问题是您想要访问三个 DATATYPE
S 的 a
字段,而不知道实际存在哪个 DATATYPE
。答案是肯定的,因为 C 规范明确指出无论 DATATYPE
存在,指针指向结构的第一个成员,因此可以安全地转换为该类型。
参见:Are there any guarantees about C struct order? 尤其是:
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. 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.
因此,以下代码允许您访问:
OBJECT* abc = malloc(sizeof(OBJECT));
abc->data = malloc(sizeof(DATATYPE1));
int* pointerToA = (int*) abc->data;
这是否是良好的编程习惯是另一个问题,我不会回答。
假设我在 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;
您需要声明您将在 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;
我假设问题是您想要访问三个 DATATYPE
S 的 a
字段,而不知道实际存在哪个 DATATYPE
。答案是肯定的,因为 C 规范明确指出无论 DATATYPE
存在,指针指向结构的第一个成员,因此可以安全地转换为该类型。
参见:Are there any guarantees about C struct order? 尤其是:
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. 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.
因此,以下代码允许您访问:
OBJECT* abc = malloc(sizeof(OBJECT));
abc->data = malloc(sizeof(DATATYPE1));
int* pointerToA = (int*) abc->data;
这是否是良好的编程习惯是另一个问题,我不会回答。