web-dev-qa-db-ja.com

ダブルポインタにメモリを割り当てますか?

メモリをダブルポインタに割り当てる方法を理解できません。文字列の配列を読み取って保存したい。

    char **ptr;
    fp = fopen("file.txt","r");
    ptr = (char**)malloc(sizeof(char*)*50);
    for(int i=0; i<20; i++)
    {
       ptr[i] = (char*)malloc(sizeof(char)*50);
       fgets(ptr[i],50,fp);
    }

これの代わりに、大きなメモリブロックを割り当てて文字列を保存します

  char **ptr;
  ptr = (char**)malloc(sizeof(char)*50*50);

それは間違っているでしょうか?もしそうなら、それはなぜですか?

16
lazy_hack

2番目の例は間違っています。これは、各メモリ位置が概念的にchar*ではなくcharを保持するためです。あなたの考えを少し変えれば、それはこれに役立ちます:

char *x;  // Memory locations pointed to by x contain 'char'
char **y; // Memory locations pointed to by y contain 'char*'

x = (char*)malloc(sizeof(char) * 100);   // 100 'char'
y = (char**)malloc(sizeof(char*) * 100); // 100 'char*'

// below is incorrect:
y = (char**)malloc(sizeof(char) * 50 * 50);
// 2500 'char' not 50 'char*' pointing to 50 'char'

そのため、最初のループは、Cで文字配列/ポインターの配列を実行する方法になります。文字配列の配列にメモリの固定ブロックを使用してもかまいませんが、メモリにポインタがなく、charsしかないため、char*ではなく単一のchar**を使用します。

char *x = calloc(50 * 50, sizeof(char));

for (ii = 0; ii < 50; ++ii) {
    // Note that each string is just an OFFSET into the memory block
    // You must be sensitive to this when using these 'strings'
    char *str = &x[ii * 50];
}
14
user7116
 char **ptr;
    fp = fopen("file.txt","r");
    ptr = (char**)malloc(sizeof(char*)*50);
    for(int i=0; i<50; i++)
    {
       ptr[i] = (char*)malloc(sizeof(char)*50);
       fgets(ptr[i],50,fp);
    }

fclose(fp);

あなたのタイプミスかもしれませんが、50 x 50マトリックスを探している場合、ループは20ではなく50でなければなりません。また、上記のメモリの割り当て後、ptr [i] [j]として、つまり2D形式でバッファにアクセスできます。

2
AnkitSahu

ダブルポインターは、別のポインターへのポインターです。したがって、次のように割り当てることができます。

char *realptr=(char*)malloc(1234);
char **ptr=&realptr;

ポインターが格納されている場所を覚えておく必要があります(この例では、ダブルポインターはスタック上のポインター変数を指しているため、関数が戻った後は無効になります)。

1
Pent Ploompuu

私は疑いを晴らすかもしれない一例を挙げます、

char **str;                              // here its kind a equivalent to char *argv[]
str = (char **)malloc(sizeof(char *)*2)  // here 2 indicates 2 (char*)
str[0]=(char *)malloc(sizeof(char)*10)   // here 10 indicates 10 (char)
str[1]=(char *)malloc(sizeof(char)*10)   // <same as above>

strcpy(str[0],"abcdefghij");   // 10 length character 
strcpy(str[1],"xyzlmnopqr");   // 10 length character

cout<<str[0]<<endl;    // to print the string in case of c++
cout<<str[1]<<endl;    // to print the string in case of c++

or

printf("%s",str[0]);
printf("%s",str[1]);  

//finally most important thing, dont't forget to free the allocated mem
free(str[0]);
free(str[1]);
free(str);
1
Abhishek D K

暗記する他のより簡単な方法

ケース-1:

step-1:char * p;

ステップ-2:以下のように読んでください

char(* p); ==> pは文字へのポインタです

今、あなたは中括弧なしでタイプ(ステップ-2)に対してmallocを行う必要があるだけです

つまり、p = malloc(sizeof(char)* some_len);

ケース-2:

step-1:char ** p;

ステップ2 :

以下のように読んでください

char *(* p); ==> pはcharへのポインタです*

今、あなたは中括弧なしでタイプ(ステップ-2)に対してmallocを行う必要があるだけです

つまり、p = malloc(sizeof(char *)* some_len);

ケース-3:

誰もこれを使用しませんが、説明のために

char *** p;

と読む

char **(* p); ==> pはchar **へのポインタです(このチェックでは上記のケース2)

p = malloc(sizeof(char **)* some_len);

1
ravi chandra

ペントの答えに追加すると、彼が正しく指摘したように、関数が戻ると、このダブルポインターを使用できなくなります。戻ってきた)。関数が戻った後にこのダブルポインタを使用したい場合は、次のようにします。

char * realptr = (char *) malloc(1234);
char ** ptr = (char **) malloc(sizeof(char *));
*ptr = realptr;
return ptr;

このため、関数の戻り値の型は明らかにchar **である必要があります。

0
Rohan Saxena