为什么我不能正确存储和引用双指针?
此代码有效:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct _node{
int nodeNumber;
int weight;
}* Node;
int main(int argc, char **argv){
Node nodeList = calloc(3, sizeof(struct _node));
// Used for testing
nodeList->nodeNumber = 9;
printf("Node Number: %d\n", nodeList->nodeNumber);
return 0;
}
但是当我尝试使结构成为双指针并像这样引用时:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct _node{
int nodeNumber;
int weight;
}** Node;
int main(int argc, char **argv){
Node nodeList = calloc(3, sizeof(struct _node));
// Used for testing
nodeList[0]->nodeNumber = 9;
printf("Node Number: %d\n", nodeList[0]->nodeNumber);
return 0;
}
我的程序运行一秒钟,然后崩溃。没有错误或任何东西。我以为用
引用结构nodeList[0]->nodeNumber = 9;
可以,但是显然不能。
我还要指出,我知道直接在struct中创建指针或双指针通常被认为是不好的做法,但这是分配的一部分,并且给出了struct定义,必须按原样使用。最终目标是制作一个数组或链接列表。根据我的理解,可以找到链接列表部分,但这就是问题所在。
-------------------------------编辑--------------- ---------------------
我已将代码更改为此:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct _node{
int nodeNumber;
int weight;
}** Node;
int main(int argc, char **argv){
Node nodeList = malloc(sizeof(struct _node *));
// Used for testing
nodeList[0]->nodeNumber = 9;
printf("Node Number: %d\n", nodeList[0]->nodeNumber);
return 0;
}
但是我的程序仍然崩溃。
答案 0 :(得分:1)
如果您坚持使用双指针,则应按以下步骤操作:
typedef struct _node{
int nodeNumber;
int weight;
} Node;
并在您的函数中:
Node **nodelist = malloc(3 * sizeof(Node *));
for (int i=0; i<3; i++)
nodelist[i]= calloc(1,sizeof(Node));
请注意,我在typedef中不使用指针,因为它非常令人困惑。相反,我将nodelist
声明为双指针。
typedef struct _node{
int nodeNumber;
int weight;
} **Node;
并在您的函数中:
Node nodelist = malloc(3 * sizeof(*nodelist));
for (int i=0; i<3; i++)
nodelist[i]= calloc(1,sizeof(*nodelist[i]));
这里,我不使用类型名,而是使用变量名来确定要分配的大小:*nodelist
将节点列表取消引用为struct _node *
,而*nodelist[i]
取消引用了实际列表。 struct _node
(请注意,i
的值在此并不重要;它仅用于向编译器指示要使用数组元素)。
人们甚至更喜欢使用变量名而不是类型名,因此将来在变量引用另一种类型时,分配会随之自动更改。
答案 1 :(得分:0)
使用
typedef struct _node{
int nodeNumber;
int weight;
}* Node;
和
Node nodeList = calloc(3, sizeof(struct _node));
您使nodeList
指向struct _node
元素数组的第一个元素。
使用
typedef struct _node{
int nodeNumber;
int weight;
}** Node;
然后nodeList
将是指向struct _node
的 pointers 指针数组的第一个元素的指针,但是由于您使用{{1 }}数组中所有这些指针将为 calloc
。取消引用NULL
指针无效,并导致undefined behavior。
此外,您的分配是错误的,因为您仍然为三个NULL
元素而不是struct _node
元素分配内存。
根据经验:切勿将指针隐藏在类型别名后面。它使代码更难以阅读,理解和维护。
答案 2 :(得分:0)
其他人回答了这个问题,但是如果有人遇到这个问题并且对如何正确执行此操作感兴趣:
type**
。那只能用于诸如可变长度的字符串表之类的东西,它不是2D数组。有关详细信息,请参见Correctly allocating multi-dimensional arrays。free()
malloc()
您的free()
。当然,在大多数情况下,操作系统都会为您执行此操作。但是通过调用free()
,我们可以在代码中的其他地方暴露和检测错误,例如内存泄漏,悬空指针等,这些都会在调用#include <stdio.h>
#include <stdlib.h>
typedef struct {
int nodeNumber;
int weight;
} Node;
int main (void)
{
Node* nodeList = calloc(3, sizeof *nodeList);
nodeList[0].nodeNumber = 9;
printf("Node Number: %d\n\n", nodeList->nodeNumber);
free(nodeList);
/****************************************************************************/
const size_t x = 2;
const size_t y = 3;
Node (*nodeList2D)[y] = calloc(x, sizeof *nodeList2D);
int count = 0;
for(int i=0; i<x; i++)
{
for(int j=0; j<y; j++)
{
nodeList2D[i][j].nodeNumber = count++;
printf("Node (%d, %d): %d\n", i, j, nodeList2D[i][j].nodeNumber);
}
}
free(nodeList2D);
return 0;
}
时表现为程序崩溃。以下是适当代码的示例,其中一个示例使用1D数组,另一个示例使用2D数组:
sizeof *nodeList2D
请注意,调用malloc / calloc时的3 * sizeof(Node)
技巧适用于所使用的类型。对于2D数组,这将为我们提供一个1D数组的大小(与var a = Url.Action(action: "GetContentByFileId", values: new { fileId = 1 });
var b = _linkGenerator.GetUriByAction(HttpContext, action: "GetContentByFileId", controller: "FileController", values: new { fileId = 1 });
var c = _linkGenerator.GetUriByAction(_httpContextAccessor.HttpContext, action: "GetContentByFileId", controller: "FileController", values: new { fileId = 1 });
相同),然后使用calloc分配2个这样的内存块。