【问题标题】:malloc and pointers to pointersmalloc 和指向指针的指针
【发布时间】:2015-12-26 11:05:39
【问题描述】:

我试图了解在使用多级指针时何时需要使用 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,并且我只使用mallocPerson 类型分配空间。第二个版本,我把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 需要malloc 空间,而*p 不需要malloc 空间?它们都是指向指针的指针?

2) 另外,为什么我不需要在第二版或第三版中为p 提供malloc 空间?

3) 在第三个版本中,malloc 对于*p 的正确大小是多少?在我的 64 位 Mac 上,sizeof(void) 为 1,sizeof(void*) 为 8,两者似乎都可以工作,但正确的是什么?

【问题讨论】:

  • 确实需要在 v2 上分配 p。你的代码错了。
  • 启用警告后重新编译,您会发现代码存在一些问题。
  • 正确的是无效的*。 void* 是一个指针,这意味着它的大小足以包含 64 位计算机中的每个内存地址。如果您的计算机使用 32 位系统,它可能会更小。 Amit 也是对的,您的第二个版本是错误的,您需要为第一个指针 (p) 分配内存。如果您使用警告标志 (-Wall -Wextra) 进行编译,您将得到:warning: ‘p’ is used uninitialized in this function [-Wuninitialized] *p = malloc(sizeof(Person));
  • @Idr 没错。尽管使用malloc(sizeof(Person*)); 而不是malloc(sizeof(void*)); 会更好,因为您已经知道要使用的类型。它不会改变任何计算机方面的内容,但会使代码更清晰。
  • @ldr 反复试验不是学习 C 的好方法,您无法判断您的代码是否正确,或者它是否已损坏但这次碰巧产生了正确的输出

标签: c pointers malloc pointer-to-pointer


【解决方案1】:
  1. 取消引用尚未初始化的指针 (*p) 在任何情况下都会引发未定义的行为。

  2. 在为指针分配空间时,您通常希望通过通常使用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;
}

【讨论】:

  • 指针到指针的非常棒的演示...谢谢!
【解决方案2】:

我只是在这里总结一下:

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

2) 您确实需要在这两种情况下分配空间,如果您打开警告(无论如何都不应该关闭),您将收到以下警告:

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-13
    • 2012-08-17
    • 1970-01-01
    • 2012-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-14
    相关资源
    最近更新 更多