ポインタを渡してヒープに領域を割り当てる方法

私は関数にcharポインタを渡そうとしています。それは呼び出し関数がそれを使用できるように、関数でそれを埋めます。呼び出し関数に奇妙なものが与えられたので、私は何をしているのか簡単な表現を書いた:

#include 
#include 

void bla(char *t)
{
    t = (char*) malloc(5);
    if (t != 0) {
        t[0] = 'h';
        printf("%c\n", t[0]);
    }
}

int main(int argc, char **argv)
{
    char b[10];

    bla(b);
    printf("%c\n", b[0]);
    return 1;
}

私は、Cが引数のコピーを渡すことを何かする必要があるかどうかはよく分かりません。ポインタへのポインタを渡す必要がありますか、それともより良い解決策がありますか?

編集:

申し訳ありませんが、私はそれを取得していない。あなたはこの例を見てください:

#include 
#include 

void blub(char **t)
{
    printf("%d\n", *t);
    *t = (char*) malloc(sizeof(char) * 5);
    *t[0] = 'a';
    *t[1] = 'b';
    printf("%d\n", *t);
    printf("%d\n", *t[0]);
    printf("%d\n", *t[1]);
}

int main(int argc, char **argv)
{
    char *a;
    blub(&a);
    printf("%d\n", a);
    printf("%d\n", a[0]);
    printf("%d\n", a[1]);

    return 1;
}

出力は次のとおりです。

./main
6154128
140488712
97
98
140488712
97
0      <== THIS SHOULD BE 98 AS ABOVE!?

なぜ私は関数blafuで98を取得し、メインでそれはnullポインタですか?私は完全に混乱している:/

0
@pluckyDuck - 私の編集を参照してください:)あなたは正しい方向です。
追加された 著者 Kiril Kirov,
そのコードはほとんど意味がありません...
追加された 著者 Mitch Wheat,
あなたの記憶をどこかで解放することを忘れないでください!
追加された 著者 Nick,

6 答え

ポインターへのポインターを使用する必要があります。

//............vv
void bla(char **t)

次に、逆参照によってポインタを使用します。

// note the '*' in front of t
*t = (char*) malloc(5);
if (*t != 0) {
    *t[0] = 'h';
    printf("%c\n", *t[0]);
}

また、 char b <10> ではなく、 bchar * として宣言します。


どうして?ポインタを変更しようとしているからです。ロジックは他のタイプと同じですが、ここではちょっと混乱します。
これについて考える: int を渡す必要があり、それを変更する必要がある場合は、 intへのポインタが必要です。同じものがここにあります - あなたは charへのポインタを渡す必要がありますので、それを変更する必要がありますので、 charへのポインタ :)


EDIT: According to your edit - yes, you have understood this perfectly, there's just a small problem - the priority of operator* and operator[]. If you replace your *t[X] with (*t)[X], everythng will be fine :)

7
追加された
あなたは私の命を救いました :)
追加された 著者 pluckyDuck,

あなたはポインタへのポインタを使用する場合

void blah(char **t)

mallocを使って(頭の中で)メモリのチャンクを割り当てることができます。

*t = malloc(size);

あなたはこのようにして電話するでしょう:

char *b;
bla(&b);

それは割り当てられ、blahで使用され、その結果はmainに出力されます。

2
追加された

関数へのポインタを渡していました。それを介して、ポインタが指し示すオブジェクトだけを永久に(関数が返された後に)変更することができますが、実際に関数に渡されるコピーなのでポインタ自体を変更することはできません。関数内のすべての変更は、ポインタのコピーで行われます。関数が返っても元の値は変更されません。

(1)ある関数の中でいくつかの変数を変更したいのであれば、それにポインタを渡す必要があります。その変数がポインタ型であれば、それにポインタを渡します - ポインタへのポインタ!あなたの場合、その変数はchar **型になります。

(2)関数内のヒープ上にメモリを割り当てる場合は、スタックを使用する必要はありません - ポインタbをchar *として宣言してください。

(3)ヒープ上にメモリを割り当てた後、メモリを解放することを忘れないでください。さもなければメモリリークが発生します。

(4)エラーなしで終了する場合、アプリケーションから0を返します。他の戻り値を保持する エラーコード - アプリで発生する可能性のあるエラーの種類が異なる場合は、別のコードを返します。

The final point is that this is a pure C application. In C++ you would use new/delete to allocate/deallocate memory, std::string instead of char* for strings, and std::cout << instead of printf for sending text to the output stream

void bla(char **pt)              //(1)
{
    *pt = (char*)malloc(5);

    if (*pt != 0) 
    {
        *pt[0] = 'h';
        printf("%c\n", *pt[0]);
    }
}

int main(int argc, char **argv)
{
    char* b = 0;                 //(2)

    bla(&b);
    printf("%c\n", b[0]);

    if(b)
    {
        free(b);                 //(3)
        b = 0;
    }

    return 0;                    //(4)
}
1
追加された

var参照を使用して結果を返す場合は、ポインタにポインタを渡すか、通常の方法で結果を返す必要があります(char * bla())。ヌルターミネーターを忘れないでください!

0
追加された

静的に割り当てられた配列を持つ char b [10]; を書くと、それ以上スペースを割り当てる必要はありません。最大10個の char < code>の値を返します。

その配列の内容を関数に変更させたい場合は、単純なポインタを渡すだけで済みます(割り当てはしません):

void bla(char *t)
{
    if (t != 0) {
        t[0] = 'h';
        printf("%c\n", t[0]);
    }
}

関数の後、 mainb の値も変更されます。

0
追加された
それは実際の問題のモデルにすぎず、mallocを使用する必要があります。
追加された 著者 pluckyDuck,

2番目の例での奇妙な振る舞いの理由は、演算子の優先順位です。 [](大括弧、配列の添え字)は*(逆参照)より優先度が高い

So, *t[1] is the same as *(t[1]). You need (*t)[1]

tはcharへのポインタへのポインタです:

*(t[1]) means "take t's address, go (sizeof(char*)) bytes ahead, dereference the address, and dereference again"

(*t)[1] means "take t's address, dereference it, go (sizeof(char)) bytes ahead and dereference again"

実際には、最初のケースでは、行動は定義されていません。なぜなら、tの後に位置の重複を取り除こうとするからです。あなたの例では、最初の値は常に出力されます。なぜなら、t [0]は参照解除のみを意味するため、2つの場合が同じになるからです。

0
追加された