简体   繁体   English

当我有一个指向结构的指针时,为什么必须使用malloc?

[英]Why do I have to use malloc when I have a pointer to a struct?

 struct element {
     int val;
     int z;
 };
 typedef struct element ELEM;

Look at this example: 看这个例子:

 int main()
 {

    ELEM z;
    z =  6;
    printf("%d",z);
 }

Everything work fine , but if I have a pointer to structure I need to write the code like this: 一切正常,但是如果我有一个指向结构的指针,则需要编写如下代码:

ELEM *z;
p = (ELEM*)malloc(sizeof(ELEM)); // Without this will not work
(*p).val = 3;
p = (ELEM*)malloc(sizeof(ELEM));
printf("%d",(*p).val);

Declaring a pointer doesn't create anything but a pointer. 声明一个指针只会创建一个指针。 Gotta have something for it to point to, which is what malloc gives you. 必须要指出一些东西这就是malloc给您的东西。

Alternatively, you could have created the struct on the stack (aka "automatic storage"): 或者,您可以在堆栈上创建该结构(也称为“自动存储”):

ELEM z;
ELEM *p = &z;
(*p).val = 3; // Also could be written as p->val = 3;
printf("%d",(*p).val);

BTW, your pointer code has an error, in that it leaks (ie loses track of) the first allocated struct: 顺便说一句,您的指针代码有错误,因为它泄漏(即失去了对第一个分配的结构的跟踪):

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);

Deleting the second malloc fixes the problem. 删除第二个malloc可解决此问题。 A full, fixed-up version that looks more like code you'd see in use: 完整的固定版本,看起来更像您在使用中看到的代码:

ELEM *p = (ELEM*)malloc(sizeof(ELEM));
p->val = 3;
printf("%d\n", p->val);
free(p);

Every malloc should have a free , unless your program releases it memory by terminating. 每个malloc应该有一个free ,除非您的程序通过终止释放它的内存。 And even then, it's nice to have the free . 即便如此,还是有free

The pointer is only the address of the object in C/C++, not the object itself. 指针仅是C / C ++中对象的地址,而不是对象本身。 In a 32-bit system, its length is always 4 bytes. 在32位系统中,其长度始终为4个字节。 When you create a pointer, it will refer to a invalid address if you don't initialize it or allocate memory for it. 创建指针时,如果不初始化或为它分配内存,它将指向无效的地址。 So you must dynamically create the object by calling malloc (in C++, you can use new keyword), then it can refer to the address of the created object. 因此,您必须通过调用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

In your first example, 在第一个示例中,

int main() {
  ELEM z;
  z =  6;
  printf("%d",z);
}

You are creating a z Elem on the stack. 您正在堆栈上创建一个z Elem This is a very efficient operation, and the language will manage the memory allocated to z for you - that is when z goes out of scope it will automatically be freed. 这是非常有效的操作,该语言将为您管理分配给z的内存-也就是说,当z超出范围时,它将自动释放。 In contrast, your second example, 相比之下,第二个例子

ELEM *z;

Creates a pointer on the stack (which is a 32-bit value on a 32-bit OS, and a 64-bit value on a 64-bit OS) but does not allocate any elements. 在堆栈上创建一个指针(在32位OS上为32位值,在64位OS上为64位值),但不分配任何元素。 That is the purpose of the malloc routine, to allocate memory on the heap. 这就是malloc例程的目的,目的是在堆上分配内存。 You may point to one (as in your example), or many different elements dynamically through your pointer into the heap and you must free memory you allocate. 您可以通过指向堆的指针动态地指向一个(如您的示例中)或许多不同的元素,并且必须释放分配的内存。

You only need to use malloc if you intend to dynamically allocate memory. 如果打算动态分配内存,则只需要使用malloc Otherwise, your pointer must point to something . 否则,您的指针必须指向某物 If you intend to use your pointer when it doesn't point to valid memory, it is undefined behavior. 如果您打算在指针不指向有效内存时使用它,则它是未定义的行为。

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;
}

Let's try to visualize it using your struct definition. 让我们尝试使用您的struct定义将其可视化。

struct element
{
     int val;
     int z;
};
typedef struct element ELEM;

When you declare a variable of this type, it is allocated in memory in a safe place, that is, the implementation won't use this memory for anything else while it is in scope. 声明此类型的变量时,会将其分配在内存中的安全位置,即,实现在范围内时不会将其用于其他任何用途。

ELEM e;

   val     z  
e[ int ][ int ]

When you declare a pointer to a variable of this type and don't initialize it, it is pointing to some undefined location. 当您声明指向该类型变量的指针并且不对其进行初始化时,它指向某个未定义的位置。

ELEM *pE;

    val      z
pE[ int  ][ int ]

This pointer, even though it has been initialized still considers itself pointing to an ELEM . 即使已初始化该指针,仍然认为自己指向ELEM The actual address that it's pointing to could be "harmless", that is, you could actually use it and not cause any run time problems. 它指向的实际地址可能是“无害的”,也就是说,您可以实际使用它,而不会引起任何运行时问题。 However, if you're lucky, if you use it you'll get a run time error, such as a segmentation fault. 但是,如果幸运的话,如果您使用它,则会遇到运行时错误,例如分段错误。 This happened because you've accessed a memory location that is illegal. 发生这种情况是因为您访问了非法的内存位置。 If you're writing, you could write over code or data and corrupt it. 如果正在编写,则可以覆盖代码或数据并破坏它。

pE must point to a safe memory location, one that has been allocated for a ELEM : pE必须指向安全的存储位置,该位置已分配给ELEM

pE = &e;

         val     e
pE -> e[ int ][ int ]

pE is now pointing to e . pE现在指向e It can safely read and write from and to this memory location without any danger. 它可以安全地从该存储位置读取和写入该存储位置,而没有任何危险。

You can also allocate memory personally for pE using malloc: 您还可以使用malloc亲自为pE分配内存:

pE = malloc(sizeof(*pE);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM