1

C の char ポインターをもっと理解しようとしていますが、1 つのことがわかります。

char ポインターを関数に渡し、ポインターが表す値を変更したいとします。以下に例を示します。

int Foo (char *(&Msg1), char* Msg2, char* Msg3){
    char *MsgT = (char*)malloc(sizeof(char)*60);
    strcpy(MsgT,"Foo - TEST");
    Msg1 = MsgT; // Copy address to pointer
    strcpy(Msg2,MsgT); // Copy string to char array
    strcpy(Msg3,MsgT); // Copy string to char pointer
    return 0;
}

int main() {
    char* Msg1; // Initial char pointer
    char Msg2[10]; // Initial char array
    char* Msg3 = (char*)malloc(sizeof(char) * 10); // Preallocate pointer memory
    Foo(Msg1, Msg2, Msg3);
    printf("Msg1: %s\n",Msg1); // Method 1
    printf("Msg2: %s\n",Msg2); // Method 2
    printf("Msg3: %s\n",Msg3); // Method 3
    free(Msg1);    
    free(Msg3);
    return 0;
}

上記の例では、char ポインターを関数に渡すために知っているすべての作業メソッドをリストしました。私が理解していないのはMethod 1です。

char *(&Msg1)関数に渡される最初の引数の意味は何Fooですか?

また、方法 2と方法 3は本やチュートリアルで広く紹介されているようで、それらの方法を配列/ポインターを渡す最も正しい方法として参照している人もます方法 1は私にはとてもいいと思います。特に API を作成するとき、ユーザーは事前にメモリを割り当てずにヌル ポインターを関数に簡単に渡すことができます。唯一の欠点は、ユーザーがメモリ ブロックを解放するのを忘れた場合にメモリ リークが発生する可能性があることです (方法 3と同じ)。Method 3 の代わりにMethod 2 または 3を使用することを好む理由はありますか?

4

2 に答える 2

6

int f(char* p)必要なメモリ位置を既に指している場合p、関数にポインタを渡す C での通常の方法です (通常、方法 2 または方法 3 のように文字配列が既に割り当てられているため)。fp

int f(char** p)この関数の呼び出し元のポインターを変更できるようにする場合pは、関数にポインターを渡す C の通常の方法です。あなたの方法1はこの例です。新しいメモリを割り当て、そのメモリがどこにあるかを呼び出し元に伝えるために使用します。ffpfp

int f(char*& p)は C ではなく C++ です。これは自動的にコンパイルされるため、C++ コンパイラを使用していることがわかります。

于 2014-07-22T15:00:29.047 に答える
0

int&type (int への参照) の引数を取るとどうなるかを考えてみましょう:

void f(int &x) {
    x++;
}

void g(int x) {
    x++;
}

int main() {
    int i = 5;
    f(i);
    assert(i == 6);
    g(i);
    assert(i == 6);
}

同じ動作は、int へのポインター ( int *x) を取得し、(*x)++ を使用して変更することで実現できます。これを行う場合の唯一の違いは、呼び出し元が f(&i) を呼び出す必要があることと、呼び出し元が無効なポインターを f に渡すことができることです。したがって、参照は一般に安全であり、可能な限り優先する必要があります。

タイプ (pointer-to-char) の引数を取るというchar*ことは、呼び出し元と関数の両方が、そのポインターを「介して」同じメモリ ブロックを参照することを意味します。が指すメモリを関数が変更するchar*と、呼び出し元に保持されます。

void f(char* p) {
    (*p) = 'p';
    p = NULL; //no efect outside the function
}

int main() {
    char *s = new char[4];
    strcpy(s, "die");
    char *address = s; //the address which s points to
    f(s);
    assert(strcmp(s, "pie") == 0);
    assert(s == address); //the 'value' of the variable s, meaning the actual addres that is pointed to by it, has not changed
}

char*&( reference-to-(pointer-to-char) ) の引数を取ることは、int& を取ることとほとんど同じです: 関数がポインタが指すメモリを変更する場合、呼び出し元は通常どおりそれを認識します。ただし、関数がポインターの(そのアドレス) を変更すると、呼び出し元にもそれが表示されます。

void f(char* &p) {
    (*p) = 'p';
    p = NULL;
}

int main() {
    char *s = new char[4];
    strcpy(s, "die");
    char *address = s; //the address which s points to
    f(s);
    assert(strcmp(address, "pie") == 0); //the block that s initially pointed to was modified
    assert(s == NULL); //the 'value' of the variable s, meaning the actual addres that is pointed to by it, was changed to NULL by the function
}

繰り返しますが、char**(pointer-to-pointer-to-char) を取り、f を use**p = 'p'; *p = NULLに変更すると、呼び出し元は同じ意味で f(&s) を呼び出す必要があります。

参照によって配列を渡すことはできないことに注意してください。つまり、s が として定義されている場合char s[4]、2 番目の例で f(s) を呼び出すと、コンパイラ エラーが発生します。

また、これは C++ でのみ機能することに注意してください。C には参照がなく、ポインターしかないためです。

通常、関数が割り当てられたメモリ ブロックへのポインターを返す必要がある場合は、char**またはを使用します。char*&これは、参照char**が存在しない C よりも C++ の方が一般的ではないためです。

参照を使用するかポインターを使用するかについては、「c++ ポインター vs 参照引数」を Google で検索するとわかるように、非常に議論の多いトピックです。

于 2014-07-22T15:02:13.653 に答える