【问题标题】:Confused in pointers of two dimensional struct对二维结构的指针感到困惑
【发布时间】:2015-10-14 18:42:29
【问题描述】:

我正在使用 malloc 创建一个动态结构。我的结构如下所示:

typedef struct
    {
        int v=;
        int t;
        struct a *prev;//points to previous struct in same row
        struct a *next;//points to next struct in same row
        //Is this correct notation?
    } a;
    a **b;

在初始化期间,我这样做:

for(i=0;i<d1;i++)
    {
        for(j=0;j<d2;j++)
        {
            if (j==0) //if first block, point to NULL
                b[i][j]->prev = NULL;
            else //else point to previous block.
                b[i][j]->prev = *(b[i] + j - sizeof(b[i][j]));
        }
    }

我收到错误无效类型参数。这里有什么问题?对于 prev,我试图首先找到当前块的地址 *(b[i]+j) 并获取前一个块的地址,减去每个块的大小,即 sizeof(b[i][j])

【问题讨论】:

  • n 添加到类型化指针T * p; 可使指针的值增加n * sizeof (T) 字节。
  • 目前显示的代码中没有struct a类型。
  • 当您遇到编译器或链接器错误时,请指定确切的错误消息。另外,int v=;?
  • 您需要typedef struct a { 等,以便struct a *prev; 表示指向此结构的指针。未标记的结构与struct a 的类型不同。

标签: c pointers multidimensional-array struct


【解决方案1】:

b[i][j] 不是指针。因此,您不能使用:

b[i][j]->prev = NULL;

使用

b[i][j].prev = NULL;

更新

可以使用以下方法创建对象之间的链接:

for(j=0;j<d2;j++)
{
    // Fix the prev link
    if (j==0) //if first block, point to NULL
        b[i][j].prev = NULL;
    else //else point to previous block.
        b[i][j].prev = &b[i][j-1];

     // Fix the next link
    if (j==d2-1) //if last block, point to NULL
        b[i][j].next = NULL;
    else //else point to next block.
        b[i][j].next = &b[i][j+1];

}

【讨论】:

  • 编译器说,分配时类型不兼容(在第二个分配中)
  • @Maxsteel,最好能发MCVE
  • @Maxsteel,a 的发布定义不正确。应该是typedef struct a { ... } a;。我不确定这是否会影响您的编译器。
  • 哈!它不是! :-S 你最新的 sn-p 仍然使用-&gt;next/prev.next/prev
  • @alk,你认为我可以按照我自己的建议 :)
【解决方案2】:

我猜你希望每行中的元素被 dlink 但不反对前行。我的看法:

void
fill(void)
{
    int d1;
    int d2;
    a **b;
    a *x;
    int i;
    int j;

    d1 = 10;
    d2 = 20;

    b = calloc(d1 * d2,sizeof(a));

    x = &b[0][0];

    for (i=0;  i<d1;  i++) {
        x->prev = NULL;
        x->next = x + 1;
        for (x++, j=1;  j<d2;  j++, x++) {
            x->prev = x - 1;
            x->next = x + 1;
        }
        x[-1].next = NULL;
    }
}

更新:

将 n 添加到指针时的指针运算。如果 n 为 1,您将 1 添加到地址,您添加的是 sizeof(*ptr)。考虑以下所有内容都是等效的:

int *xp;
int n;

(A1) xp += n;
(A2) xp = (int *) (((unsigned long) xp) + (n * sizeof(int)))
(A3) xp = &xp[n];
(A4) xp = (int *) (((char *) xp) + (n * sizeof(int)))

盯着这个看一会儿,直到你真正明白为什么这是真的。这是。添加到指针的值应该完全等于相同类型数组的索引值。

您的代码在以下几个方面被破坏:
- 您需要将 b[i][j]-&gt;prev 替换为 b[i][j].prev,因为 b[i][j] 已经完全取消引用指针 [这是其他人指出的]
- 当你在做*(b[i] + j - sizeof(b[i][j]) 时,我什至不确定你会得到什么。
- 你想要&amp;b[i][j-1] (A3)。您的代码 [如果它有效的话],可能会产生 &amp;b[i][j-18]
- 这是因为您的混合指针算术和字节大小(例如,您正在对上面的 (A1)、(A2) 和 (A3) 进行混搭 - 您可以使用其中之一,但不能同时使用两者/全部)时间)

我的代码只需要在开头设置一个指针,因为它在内部循环中递增 1。
请注意,在完成“j 循环”后,x == &amp;b[i][d2] 也是&amp;b[i+1][0]。这可能有助于使其更清晰。
此外,我在内部 j 循环之前处理 j==0 情况,然后修复“j==d2-1”情况。这样,内部循环内没有 if 以及为什么它从 1 开始,而不是 0
注意x[-1].next(案例A3)是(x - 1)-&gt;next(案例A1)

这里的循环稍微重新编码以更简单/更快。它假设一个附加变量:a *ep;

for (i=0;  i<d1;  i++) {
    x->prev = NULL;
    x->next = x + 1;
    ep = x + d2;
    for (x++;  x<ep;  x++) {
        x->prev = x - 1;
        x->next = x + 1;
    }
    x[-1].next = NULL;
}

我认为你已经足够让你的代码工作了。在那之后,试着理解你的代码和我的代码,以及为什么两者都以它们的方式工作。这样做将使您在处理指针和指针算术方面有所帮助,并且很快就会像通过普通的固定大小数组进行索引一样容易。快乐编程...

【讨论】:

  • 我没有设置 x 而不是 b 的下一个/上一个吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多