malloc和指向指针的指针

malloc和指向指针的指针,c,pointers,malloc,pointer-to-pointer,C,Pointers,Malloc,Pointer To Pointer,我试图理解在使用多级指针时何时需要使用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)

我试图理解在使用多级指针时何时需要使用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;
}
我仍然只使用一个
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(Person));
    strcpy((*p)->first, "John");
    strcpy((*p)->last, "Doe");

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

    return 0;
}
#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;
}
#包括
#包括
#包括
int main(){
类型定义结构{
字符优先[10];
最后一个字符[10];
}人;
个人***p;
*p=malloc(sizeof(void));
**p=malloc(人数);
strcpy((**p)->第一个是“John”);
strcpy((**p)->最后一个“Doe”);
printf(“第一个:%s最后一个:%s\n”,(**p)->First,(**p)->Last);
返回0;
}
我的问题是:

1) 为什么在第三版中我需要
malloc
空间来存放
**p
,但我不需要
malloc
空间存放
*p
?它们都是指针对指针

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


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

我只想在这里总结一下:

1) 您确实需要为
*p
分配空间。如果使用valgrind运行第二个程序,您将看到alloc大小的错误(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*)

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

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

  • 在为指针分配空间时,您通常希望使用
    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;
    }
    
    #包括
    #包括
    #包括
    类型定义结构{
    字符优先[10];
    最后一个字符[10];
    }人;
    内部主(空){
    个人***p;
    p=malloc(sizeof*p);
    *p=malloc(sizeof**p);
    **p=malloc(尺寸***p);
    strcpy((**p)->第一个是“John”);
    strcpy((**p)->最后一个“Doe”);
    printf(“第一个:%s最后一个:%s\n”,(**p)->First,(**p)->Last);
    免费(**p);
    自由(*p);
    自由基(p);
    返回0;
    }
    
    您确实需要在v2上分配
    p
    。您的代码错误。请在启用警告的情况下重新编译,您会发现代码存在一些问题。正确的代码是void*。void*是一个指针,表示其大小足以包含64位计算机中的每个内存地址。如果您的计算机使用32位系统,它可能会更小。同样,Amit是对的,您的第二个版本是错误的,您需要为第一个指针(p)分配内存。如果使用警告标志(-Wall-Wextra)编译,您将得到以下结果:
    warning:“p”在此函数中未初始化使用[-Wuninitialized]*p=malloc(sizeof(Person))@Idr,没错。尽管使用
    malloc(sizeof(Person*)更好而不是
    malloc(sizeof(void*)因为您已经知道要使用的类型。它不会改变任何计算机方面的东西,但会使代码更清晰。@ldr试错法不是学习C的好方法,你无法判断你的代码是否正确,或者它是否被破坏,但这次恰好产生了正确的输出非常棒的指针对指针的演示。。。谢谢