【问题标题】:Void pointer to struct pointer inside a structure without dereferencing it指向结构内结构指针的无效指针而不取消引用它
【发布时间】:2017-06-17 06:21:16
【问题描述】:

假设我在 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;

【问题讨论】:

  • 1) 除了宏或枚举常量之外,不要使用全大写的名称。 2) 不要在没有真正需要的情况下使用void *。编写类型安全的代码! 3) 编译器应该如何知道您的 void * 指向的类型而不需要强制转换? 4) 您尝​​试解决的实际问题是什么?
  • 这就是我不知道的重点。但是有什么方法可以在附近工作吗?
  • 可以吗?也许(如果你能明确第 4 点)。实际的问题是:你应该吗?哪个更容易回答:NO!
  • 我想尝试看看是否可能的一点是,我是否可以通过 void 指针使用结构字段而不使用DATATYPE1* dt1 = malloc(sizeof(DATATYPE1));
  • 请读一本C书!这与动态内存分配无关。没有冒犯,但是您要么有一些基本的误解,要么您无法正确解释问题。两者都是编写适当程序的必要先决条件。

标签: c pointers struct void-pointers


【解决方案1】:

我认为问题在于您想访问三个DATATYPES 的a 字段,而不知道实际存在哪个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;

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

【讨论】:

    【解决方案2】:

    您需要声明将在 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;
    

    【讨论】:

    • 不需要任何这些演员表,但这里的一切似乎都是正确的。但是,很难确定这是否真的回答了这个问题,因为 OP 似乎有点不确定他想知道什么。尽管如此,工会确实可能是 OP 解决问题的好方法。
    • 我同意你的看法。我试图向他展示我认为可以产生与他的愿望非常相似的代码。感谢您对演员表的评论,他们真的没有必要。
    猜你喜欢
    • 2013-01-04
    • 2011-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-24
    • 2023-04-07
    • 2018-05-16
    相关资源
    最近更新 更多