malloc 和指向指针的指针

malloc and pointers to pointers

我正在尝试了解在使用多级指针时何时需要使用 malloc。例如,

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    typedef struct {
        char first[10];
        char last[10];
    } Person;

    Person *p;

    p = malloc(sizeof(Person));
    strcpy(p->first, "John");
    strcpy(p->last, "Doe");

    printf("First: %s Last:%s\n", p->first, p->last);

    return 0;
}

在第一个版本中,我使用 Person *p,并且我只使用 malloc 为类型 Person 分配 space。在第二个版本中,我将 Person *p 更改为 Person **p

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    typedef struct {
        char first[10];
        char last[10];
    } Person;

    Person **p;

    *p = malloc(sizeof(Person));
    strcpy((*p)->first, "John");
    strcpy((*p)->last, "Doe");

    printf("First: %s Last:%s\n", (*p)->first, (*p)->last);

    return 0;
}

我仍然只使用一个 malloc 即使现在有另一个指针。

在第三个版本中,我将使用 Person ***p

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    typedef struct {
        char first[10];
        char last[10];
    } Person;

    Person ***p;

    *p = malloc(sizeof(void));
    **p = malloc(sizeof(Person));
    strcpy((**p)->first, "John");
    strcpy((**p)->last, "Doe");

    printf("First: %s Last:%s\n", (**p)->first, (**p)->last);

    return 0;
}

我的问题:

1)为什么我在第3版中**p需要mallocspace,而我不需要mallocspace *p?它们都是指向指针的指针?

2) 另外,为什么我不需要 malloc space for p in either the 2nd or 3rd version?

3) 在第三个版本中,*p malloc 的正确大小是多少?在我的 64 位 Mac 上,sizeof(void) 是 1,sizeof(void*) 是 8,两者似乎都有效,但哪个是正确的?

我只是想把这个放在这里做总结:

1) 您确实需要为 *p 分配 space。如果您 运行 使用 valgrind 的第二个程序,您将看到分配大小错误(1 而不是 8); *p 是指向指针的指针,但 **p 不是,它是指向结构的指针。

2) 你确实需要在这两种情况下分配 space,如果你打开警告(无论如何你都不应该关闭),你会收到这个警告:

warning: ‘p’ is used uninitialized in this function [-Wuninitialized] *p = malloc(sizeof(Person));

3) 右边的是void*void* 是一个指针,这意味着它的大小足以包含 64 位计算机中的每个内存地址。如果您的计算机使用的是 32 位系统,它可能会更小。虽然使用

会更好

malloc(sizeof(Person*)); 而不是 malloc(sizeof(void*));

因为您已经知道要使用的类型。它不会改变计算机方面的任何东西,但会使代码更清晰。

  1. 取消引用一个尚未初始化的指针 (*p) 在任何情况下都会引发未定义的行为。

  2. 在将 space 分配给一个指针时,您通常希望通过通常使用 sizeof 运算符为其分配内存,其大小与它指向的内存大小相同。后一种情况是 1. 的唯一例外,它允许编码 *p.

所以第三个例子看起来像这样

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
        char first[10];
        char last[10];
} Person;

int main(void) {
    Person ***p;

    p = malloc(sizeof *p); 
    *p = malloc(sizeof **p);
    **p = malloc(sizeof ***p);
    strcpy((**p)->first, "John");
    strcpy((**p)->last, "Doe");

    printf("First: %s Last:%s\n", (**p)->first, (**p)->last);

    free(**p);
    free(*p);
    free(p);

    return 0;
}