最近这个问题是在堆栈溢出时被问到的,但是我对内存分配有不同的疑问。
在Graph *G=malloc(sizeof(*G))
行中,这里的内存分配是指向Graph
的指针,如果您要说的是,在其他结构中都没有发生针对其他结构成员的内存分配,那么我们如何使用G->var
访问它们,因为我们只为(*G)
分配了可能等于某个int值的内存?
如果您说:
它正在分配Graph结构并将G分配给该结构的地址
比Graph *g = malloc( sizeof( Graph ) );
还可以。
struct Edge {
int vertex;
int weight;
Edge *next;
};
struct Graph {
int v;
Edge **edge;
int *dist;
int *path;
};
Graph *graph_new(int v)
{
Graph *G = malloc(sizeof(*G));
G->v = v;
G->edge = calloc(v, sizeof(*G->edge));
G->dist = calloc(v, sizeof(*G->dist));
G->path = calloc(v, sizeof(*G->path));
return G;
}
答案 0 :(得分:0)
...如何使用G-> var ...
看来您不清楚指针是什么。指针是一个简单的变量,您可以像其他任何变量一样读写。但是,您可以对指针执行更多操作:取消引用(使用*或->)。为了执行此特定操作,指针的值必须有效:指针包含一个地址,如果该地址无效,则会发生错误。将指针视为信封,无论是否书写。您可以阅读信封上写的内容。您也可以擦拭并在上面写字。但是,当您阅读信封上写的地址时,您希望该地址存在,否则您可以四处寻找一个不存在的地址,然后生气。
可以认为指针的特定值类似于整数。您可以采用任何整数并执行计算,但是,如果要对其进行除,则您的整数必须不同于0,否则会发生错误。指针也是如此:您可以读取它并以任何值写入它,但是,如果要使用其值通常应该是什么,即内存中的地址,则该值必须指向一个合适的值地址。 malloc()和calloc()返回有效且适合分配给指针的值,并且在尝试取消引用指针时可以安全地使用(在正常情况下)。
在下面的评论后进行编辑。 通常认为,如果不能保证程序正常运行,那就是错误。为了使程序始终能够正确运行,必须采取许多预防措施。其中两个是1)不要使用未知值,以及2)不要取消引用无效的指针。错误可以按照术语,样式或它们产生或可以产生的效果进一步细分。未定义的行为是C语言规范给出的名称,用于表示编译器(或目标计算机)可以执行他们想要的任何操作,因为该规范并未强制要求任何精确的操作。当然,没有人希望“未定义的行为”,因此,使之发生只是错误。回到取消引用错误的指针,该规范说它调用了未定义的行为。确切地说,取决于目标计算机和操作系统,可能会发生以下一种或多种情况:1)除了读取未知值外,什么都没有; 2)除了写入未知的存储区外,什么都没有; 3)段故障或其他陷阱/异常等; 4)CPU过热,爆炸或其他未指定的事物。
现在,我们向前迈出了一步。如果指针变量不是“普通”全局变量,而是驻留在动态(未分配)内存中,则该变量尚不存在。这是一个概念,而不是真正的变量。因此,首先创建该变量;那么您就可以按照之前说的那样使用它。
在您的示例中,“结构图”是一堆变量的声明,这些变量在您分配它们之前不存在。一旦完成,就可以通过“ Graph * G = malloc(sizeof(* G));”来实现;但这并不意味着它们具有有效值。实际上,在代码片段的创建下面,就可以访问它们。目前,对他们的唯一合法访问是为其分配一些价值。如前所述,它们也可以被读取-它们确实存在,但是其值可能(是IS)是非法的。
如果刚创建的结构图中的值是简单的整数而不是指针,则问题将是相同的:变量存在,但其内容未知,因此无效。请注意,您可以使用calloc()分配结构图:在这种情况下,内部变量的值将是未知的,但是对于指针而言,将其无效仍将被取消引用-就像已知为零的整数,因此无效用作除数。但是变量在那里,可以针对0(对于整数)进行测试,对于指针(对于NULL)(或0)进行测试,或者可以使用有意义的值进行写入。
希望我已经足够清楚地提供帮助。
答案 1 :(得分:0)
Graph *G=malloc(sizeof(G))
!= Graph *G=malloc(sizeof(*G))
G是图形的指针,因此,sizeof(G)
在第一种情况下为Graph *
分配内存。
在第二种情况下,sizeof(*G)
为G指向的内容分配足够的内存 ,在这种情况下为Graph
。
您如何选择分配内存完全取决于您,并且取决于您打算做什么。
第二,如果您在struct Graph
中的结构中具有作为指针的字段,则这些字段将保持未分配状态,任何访问它们的尝试都将导致错误,直到您为它们正确分配内存或将它们指向有效为止内存位置。