struct element {
int val;
int z;
};
typedef struct element ELEM;
看看这个例子:
int main()
{
ELEM z;
z = 6;
printf("%d",z);
}
一切正常,但如果我有一个指向结构的指针,我需要编写如下代码:
ELEM *z;
p = (ELEM*)malloc(sizeof(ELEM)); // Without this will not work
(*p).val = 3;
p = (ELEM*)malloc(sizeof(ELEM));
printf("%d",(*p).val);
答案 0 :(得分:7)
声明指针不会创建除指针之外的任何内容。必须有一些东西可以指向,这是malloc
给你的东西。
或者,您可以在堆栈上创建结构(a.k.a。“自动存储”):
ELEM z;
ELEM *p = &z;
(*p).val = 3; // Also could be written as p->val = 3;
printf("%d",(*p).val);
顺便说一下,你的指针代码有一个错误,因为它泄漏了(即丢失了)第一个分配的结构:
ELEM *p;
p = (ELEM*)malloc(sizeof(ELEM));
(*p).val = 3;
p = (ELEM*)malloc(sizeof(ELEM)); // <- leak here: pointer to old struct lost.
printf("%d",(*p).val);
删除第二个malloc
可解决问题。一个完整的,已修复的版本,看起来更像您在使用中看到的代码:
ELEM *p = (ELEM*)malloc(sizeof(ELEM));
p->val = 3;
printf("%d\n", p->val);
free(p);
每个malloc
应该有free
,除非您的程序通过终止释放内存。即便如此,拥有free
。
答案 1 :(得分:4)
指针只是C / C ++中对象的地址,而不是对象本身。在32位系统中,其长度始终为4个字节。当您创建指针时,如果您没有初始化它或为其分配内存,它将引用无效的地址。因此,您必须通过调用malloc
动态创建对象(在C ++中,您可以使用new
关键字),然后它可以引用所创建对象的地址。
ELEM elem; //This will create the object at stack.
ELEM* pElem; //This just create an invalid poiter which point to unknown address
pElem = &elem; //This initialize the pointer which point to the address if "elem" above
pElem = (ELEM*)malloc(sizeof(ELEM)); //This create a new memory which contain the object "ELEM" and pElem will point to the address of the object
答案 2 :(得分:1)
在你的第一个例子中,
int main() {
ELEM z;
z = 6;
printf("%d",z);
}
您正在堆栈上创建z
Elem
。这是一个非常有效的操作,语言将为您管理分配给z
的内存 - 即z
超出范围时,它将自动被释放。相比之下,你的第二个例子,
ELEM *z;
在堆栈上创建一个指针(在32位操作系统上为32位值,在64位操作系统上为64位值),但不分配任何元素。这就是malloc
例程的目的,即在堆上分配内存。您可以通过指向堆的指针动态地指向一个(如在您的示例中)或许多不同的元素,并且您必须释放您分配的内存。
答案 3 :(得分:0)
如果您打算动态分配内存,则只需使用malloc
。否则,您的指针必须指向某事。如果您打算在没有指向有效内存的情况下使用指针,则它是未定义的行为。
struct Elem
{
int val;
};
int main() {
struct Elem elem;
struct Elem* ptr; // can't use pointer, points to nothing
ptr = &elem; // good, points to elem
ptr->val = 5;
printf("%d", ptr->val);
ptr = malloc(sizeof(struct Elem)); // good, points to object on the heap
ptr->val = 10;
printf("%d", ptr->val);
free(ptr);
return 0;
}
答案 4 :(得分:0)
让我们尝试使用您的struct
定义对其进行可视化。
struct element
{
int val;
int z;
};
typedef struct element ELEM;
当你声明一个这种类型的变量时,它会在内存中安全地分配,也就是说,当它在范围内时,实现不会将此内存用于其他任何内容。
ELEM e;
val z
e[ int ][ int ]
当声明指向此类型变量的指针并且不初始化它时,它指向某个未定义的位置。
ELEM *pE;
val z
pE[ int ][ int ]
该指针即使已经初始化,仍然认为自己指向ELEM
。它所指向的实际地址可能是“无害的”,也就是说,您实际上可以使用它而不会导致任何运行时问题。但是,如果您很幸运,如果您使用它,您将收到运行时错误,例如分段错误。发生这种情况是因为您访问了非法的内存位置。如果你正在写作,你可以写代码或数据并破坏它。
pE
必须指向一个安全的内存位置,一个已为ELEM
分配的位置:
pE = &e;
val e
pE -> e[ int ][ int ]
pE
现在指向e
。它可以安全地从这个内存位置读写,没有任何危险。
您还可以使用malloc:
为pE
个人分配内存
pE = malloc(sizeof(*pE);