6

複数レベルのポインターを使用するときに、いつ 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;
}

私が使用しているこの最初のバージョンでは、 type の割り当てスペースPerson *pのみを使用しています。2番目のバージョンでは、次のように変更しますmallocPersonPerson *pPerson **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別のポインターがあるにもかかわらず、私はまだ1つしか使用していません。

この 3 番目のバージョンでは、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 番目のバージョンでは のmallocスペースが必要なのに、 のスペースは必要ないのはなぜですか? どちらもポインターへのポインターですか?**pmalloc*p

2) また、 2 番目または 3 番目のバージョンでmallocスペースを確保する必要がないのはなぜですか?p

3) 3 番目のバージョンでは、 の適切なサイズmalloc*p? 私の 64 ビット Mac ではsizeof(void)は 1 で、sizeof(void*)は 8 で、どちらも動作しているように見えますが、どちらが正しいのでしょうか?

4

2 に答える 2

7
  1. 初期化されていないポインタ ( *p) を逆参照すると、いずれの場合も未定義の動作が発生します。

  2. sizeofポインターにスペースを割り当てるとき、通常は演算子を使用して、ポインターが指しているサイズのメモリをポインターに割り当てたいと思うでしょう。この後者のケースは、コーディングを許可する 1. に対する唯一の例外です*p

したがって、3番目の例は次のようになります

#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;
}
于 2015-12-26T15:00:11.483 に答える
5

要約するためにここにこれを置くつもりです:

1) にスペースを割り当てる必要があります*p。2 番目のプログラムを valgrind で実行すると、割り当てサイズのエラーが表示されます (8 ではなく 1)。*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*));

使用するタイプがすでにわかっているためです。コンピューターに関しては何も変更されませんが、コードがより明確になります。

于 2015-12-26T11:58:46.107 に答える