C:分配内存时混淆类型

时间:2013-05-30 14:12:39

标签: c

对于以下图表声明(我无法更改 - 赋值),

#define TAG(vp)   ((vp)->tag)
#define LABEL(vp) ((vp)->label)  
#define EDGE(vp)  ((vp)->edge)

typedef struct vertex 
{
    char tag;
    char *label;
    struct vertex *edge[1];
}
vertex, *vp;       

当我使用以下行分配内存时

EDGE (test) = (vp *) malloc (sizeof (vp) * 3); // where test is a node of a graph

我收到以下错误

error: incompatible types when assigning to type ‘struct vertex *[1]’ from type ‘struct vertex **

此外,我无法将EDGE指定为NULL。我想我遗漏了一些声明(它使用了* ptr [1]这让我很困惑)。你能帮忙吗?

提前致谢。

4 个答案:

答案 0 :(得分:5)

您正在查看的是名为"struct hack"的C99前代码。在C99或更高版本中,您使用的是flexible array member

一般的想法是你通过数组成员分配结构加上一些额外的空间:

struct vertex *v = malloc(sizeof *v + n * sizeof(struct vertex *));

n边分配一个带空格的结构(以及下面提到的@EricPostpischil中的标记)。我没有使用你的*vp typedef,因为我不喜欢通过typedef隐藏指针类型。

在分配之后,您可以像平常一样使用数组:

v->edge[0] = &someOtherVertex;
v->edge[1] = &someOtherOtherVertex;

等等。

答案 1 :(得分:2)

如果每个顶点只需要一条边:

struct vertex *edge;

否则你可以修改你的宏(ug?为什么?),例如:

#define EDGE(vp)  ((vp)->edge[0])

但您可能想要第一个选项,因为您似乎是动态创建数组。

你不能做的是分配给数组本身:要么使它成为指针,要么指定给数组的(唯一)元素。

请注意,C中用于创建动态数组的通常习惯用法是声明一个普通指针并使其指向动态数组的第一个元素。

答案 2 :(得分:0)

使用现有的Linux系统程序,cdecl我可以看到

 struct vertex *edge[1];

平均:

adi@laps:~$ cdecl
Type `help' or `?' for help
cdecl> explain struct vertex *edge[1];
declare edge as array 1 of pointer to struct vertex
cdecl> 

因此,您指定的数据结构将来自顶点的边表示为存储在结构中的指针。因为你没有任何边数的计数,所以你可以使用一个标记为NULL的标记来标记数组的末尾。

因此EDGE(vp)[0]是第一个重合顶点,EDGE(vp)[1]是第二个,等等,直到你读到NULL。

这称为尾随数组习惯用法,你必须记住sizeof(struct vertex)是没有边缘(只有哨兵)的顶点所需的内存量,每当添加更多边时一个顶点,你必须确保为保存结构的块分配了足够的内存。

另外,这个成语已经在C99中被标准化为灵活数组,不同之处在于你没有声明数组的大小

 struct vertex {
      struct vertex* edge[];
 }

答案 3 :(得分:0)

而不是

EDGE (test) = (vp *) malloc (sizeof (vp) * 3);

你需要做

EDGE (test) = malloc (sizeof (vp)); // to allocate array of pointer to vertex
EDGE (test)[0] = malloc (sizeof (vertex)); // to allocate the vertex itself.

如果你不能改变

struct vertex *edge[1];