繁体   English   中英

定义一个结构,该结构的成员指向另一个成员

[英]Define a struct with a member pointing to another member

我正在尝试用C编程网络。我有相互链接的节点,我想通过使struct成员指向另一个成员(而不是另一个节点)来实现这一点,因为我想保留身份的链接)。 我要做的代码是这样的:

struct node{
    int k; //number of links
    struct node.link **link; //<- wrong
};

但这是不对的,因为节点不是变量而是变量类型(这在另一个质量检查中已经作为错误进行了讨论:首先,您必须定义节点类型的变量,然后应用.link,但这不是在这里帮助)。 还有一个称为“结构成员指向另一个结构成员”的质量检查,但他们不是从定义中进行的,而且不清楚如何将其归纳(至少对我而言)。

这是正确的方法吗?

问题是C语言不允许您创建所需的类型。 你需要一个类型T与物业*T具有相同类型的T 你不能那样做。 (好吧,函数指针具有该属性,但这与技术无关。)

您必须引入一个新名称。 C仅允许您使用结构或类似构造来执行此操作。

struct link {
    struct link *ptr;
};
struct node {
    int k;
    struct link *link;
};

这将为您提供所需的东西。 现在,为了从struct link *struct node * ,您必须做一些指针数学运算:

struct node *node_from_link(struct link *link) {
    return (struct node *) ((char *) link - offsetof(struct node, link));
}

这也是由container_of宏提供的,它不是C标准的一部分,但是您可以在线找到它的定义。

或者,您可以走传统路线。

// Usually easier to do it this way...
struct node {
    int k;
    struct node *link;
};

这是你所追求的吗?

struct Node
{
    int k; //number of links
    void* link; 
};

struct Node* create()
{
    struct Node* node = malloc(sizeof(struct Node));
    node->k = 0;
    node->link = 0;
    return node;
}

void link(struct Node* from, struct Node* to)
{
    from->link = &(to->link);
}

int main()
{
    struct Node* child = create();
    struct Node* parent = create();
    link(parent, child);
    return 0;
}

由于Dietrich表示的原因,我对链接使用了void* :您希望指向链接的指针与链接的类型相同。 这实际上意味着强制转换,那么为什么不只使用通用指针呢?

通用或特定结构中的成员资格不是C数据类型的属性。 因此,没有办法声明只能指向结构成员,而不能指向任何其他兼容类型变量的指针。

另一方面,您无需执行任何特殊操作即可声明可以指向另一个结构的成员的指针。 您只需要指向该成员的数据类型的指针,并且结构成员资格与该数据类型无关。

例如,您可以

struct node {
    int k; /* number of links */
    struct node **links; /* points to a dynamic array of node pointers */
    struct node **one_link; /* points to a node pointer from another node */
};

在这种情况下,执行以下操作可能很有意义:

struct node *n1 = /* ... */;
struct node *n2 = /* ... */;

n2->one_link = &(n1->links[3]);

总的来说,我认为这有点令人费解。 可能有更好的方法来组织数据。

更新:

根据您对所追求的内容的描述:

链接是双向的,如果我销毁一个链接(例如,将节点1链接到节点3的链接),则需要销毁节点1的链接和来自节点3的相应链接。然后我需要了解更多不仅仅是谁链接到谁。 我需要知道他们正在使用哪个链接。

至少有两种可能的解决方案,具体取决于节点结构的详细信息。 如果它们的结构如我上面显示的那样,并且具有指向其他节点的指针数组(无论是否动态),那么您的一般想法将完全无效。 这是因为在删除其他链接时(假设您缩小了间距),链接数组中每个链接的位置都会改变。 相反,您可以扫描:

struct node {
    int k; /* number of links */
    struct node **links; /* points to a dynamic array of node pointers */
    struct node *parent; /* points to a node that links to this one */
};

void delete_node(struct node *n) {
    if (n->parent) {
        int i;

        for (i = 0; i < n->parent->k; i += 1) {
            if (n->parent->links[i] == n) {
                /* ... delete the ith element of n->parent->links ... */
                break;
            }
        }
    }

    /* ... clean up node n ... */
}

另一方面,如果一个节点与其他节点的链接存储在单独的成员中,则您确实可以提供一个双指针,通过该指针可以从父节点删除链接,但是原始结构中成员k的存在告诉我,这不是您的情况。

好的,这就是我最终在程序中解决它的方式:

typedef struct node{
int k; //connectivity
struct link **enlace; //vector of LINKs
}NODE;

typedef struct link{
NODE *node1;
NODE *node2;
}LINK;

基本上,我定义了两种结构:一种是NODE类型,它包含节点如何连接以及LINK向量的信息,另一种是LINK结构,其中包含链接本身的信息,我的意思是链接连接。

通过这两个,我能够按照Poisson分布创建具有连通性的节点网络,然后一个一个地破坏每个链接,从列表中随机选择一个链接,然后将每个节点的指针重定向到NULL。

暂无
暂无

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

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