2017-06-17 6 views
0

だから私は動作するものを明確にするために探しています。私は何が起こっているのか理解していると確信していますが、私の仕事を進める前に確かめたいと思っていました。メモリ参照はダブルポインタに送信されました

name* createName(char* firstName, char* lastName) 
{ 
    name* newName = (name*)malloc(sizeof(name)); 

    initStringValue(&newName->firstName, firstName); 
    initStringValue(&newName->lastName, lastName); 

    newName->firstNameSize = strlen(newName->firstName); 
    newName->lastNameSize = strlen(newName->lastName); 

    return newName; 
} 

構造「名前」がそうのように定義されています:

struct name 
{ 
    char* firstName; 
    char* lastName; 

    int firstNameSize; 
    int lastNameSize; 
}; 

名の文字列のコピーを担当する別の機能は以下のように書かれている

私は次のように関数が定義されています以下:

void initStringValue(char** destination, char* source) 
{ 
    int length = strlen(source) + 1; 
    int size = length * sizeof(char); 
    *destination = (char*)malloc(size); 
    memset(*destination, 0, size); 
    strcpy(*destination, source); 
} 

ここで行ったことを理解している場合は、&演算子私は、値ではなく関連するメモリアドレスを送信したいと言ってきました。構造体のメンバのfirstNameのは、私はメモリ・アドレスであることを起こるこのポインタのメモリアドレスではなくポインタ値を(送信したいことが示されました*文字で、次のような命令

&newName->firstName 

でそれ自体の)。 - >演算子はポインタのメンバへのこのポインタを参照解除しますが、&演算子は代わりに私たちをfirstNameメモリ参照に戻し、そのメモリ参照の情報を操作できます。

これで野生になりました(とにかく私にとって)。そのメモリ参照で実際に動作するために、私はダブルインダイレクション(非常に受動的な攻撃的)を使用してしまいます。それは、initStringValue関数のchar ** destinationのようなchar **に送信されたメモリー参照(& newName-> firstNameのようなもの)が、返されたメモリー参照が割り当てられたポインターのポインターになります& newName-> firstName * destinationを使って、私は& newName-> firstNameのメモリ参照を指しているポインタを使って作業しています。別の言い方をすれば、最初の唯一のメンバがnewName-> firstNameのメモリ参照であるポインタ。

これを正しく理解していますか?

+2

まず関連していない言語タグを使用しないでください。 Cでプログラミングしている場合は、そのタグだけを使用してください。今あなたの質問のために、あなたがやっていることは*参照を呼び出す*エミュレートです。 'cでリファレンスを呼び出すことをエミュレートする 'を検索した場合、たくさんのヒットが得られるはずです。 –

+1

あなたが正しいかのように聞こえます。関数がポインタの値を変更したいときは、関数にそのポインタへのポインタを与える必要があります。それは他のどのタイプとも変わりません。もし関数が 'int'を変更したければ、' int'へのポインタを渡す必要があります。同じこと。ポインタの場合は、ポインタへのポインタ関数のパラメータ(別名**)で終わることになります。ポインタ変数には他の変数と同様に値が入っていることに注意してください。 – 4386427

+2

'initStringValue'に' memset'を実行してすぐにゼロを上書きする理由はありません。 – stark

答えて

2

これは正しく理解していますか?

あなたの説明を読んだ後、私はいくつかの例でそれを説明しようはい

を言いますよ。

あなたがこれを行う場合は、次の

void foo(int a) 
{ 
    a = 5; 
} 

int main() 
{ 
    int a = 10; 
    foo(a); 
    printf("%d\n", a); 
    return 0; 
} 

あなたは出力が得られます:10関数のパラメータは、関数のローカル変数であるためだ

。言い換えれば、関数パラメータに加えられた変更は、関数が戻るときに失われます。つまり、mainの変数は変更されません。

変数の値をmain(別名呼び出し元)に変更するには、ポインタを渡す必要があります。同様に:

void foo(int* a) // notice int* 
{ 
    *a = 5;  // notice *a 
} 

int main() 
{ 
    int a = 10; 
    foo(&a);  // notice &a 
    printf("%d\n", a); 
    return 0; 
} 

この意志出力:5

これは、種類に関係なく一般的なルールです。この例ではintを使用しましたが、どのタイプのポインタにも適用されます。

それでは、ポインタでの例を見てみましょう:

void foo(char** a, int size) // notice char** 
{ 
    *a = malloc(32);   // malloc memory 
    strcpy(*a, "Hello world"); // copy some data into the memory 
} 

int main() 
{ 
    char* a = NULL; // a is not pointing to anything yet 
    foo(&a); 
    // Now a points to the malloc'ed memory 
    printf("%s\n", a); 
    return 0; 
} 

この意志出力:すべてのHello world

+0

答えをありがとう!私が右の道にいることを喜んで。私は将来、CやC++に固執しようとしますが、それは混乱を招くようです。 – Mike

関連する問題