2017-10-23 13 views
-1

パラメータとして渡されたときに関数がポインタの状態をどのように変更するのか分かりません。たとえば、このコードでは -関数内のポインタの振る舞い

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

void inc(int* a) { 
    a++; 
} 

void change(int* a) { 
    a[0] = 2; 
    a[1] = 3; 
} 

int main() { 

    int* a = (int*) malloc(2 * sizeof(int)); 
    a[0] = 1; 
    a[1] = 2; 

    printf("%d \n",*a); 
    inc(a); 
    printf("%d \n",*a); 

    change(a); 
    return 0; 
} 

私が機能inc()を使用して実行しようとするとき、ポインタをインクリメントしないことが観察されます。 しかし同時に、change()は実際にポインタの値を変更します。

inc()はなぜ機能しないのですか?

+0

'c 'のすべてが値渡しです。どちらの関数でも、 'a'のローカルコピーが作成されます。 'inc'では、そのローカルコピーをインクリメントするだけで、変更を失ったときに失われます。 'change'では、' a'ポインタのローカルコピーを括弧で間接参照するので、その逆参照に加えられた変更はその関数の外で持続します。 – yano

+0

* "change()は実際にポインタの値を変更します" * - これは** pointed to **オブジェクトを変更します。 – StoryTeller

答えて

0

incそれに渡されたポインタの変更値を行います - しかし、何それに渡されたのは、元のポインタ値のコピーなので、元は変わりません。

changeポインタ自体は変更されません。ポインターが指しているものが変更されます。

あなたはincあなたは、元のポインタに割り当てたいインクリメントポインタを返す関数であるようにそれを変更するには、どちらかにあります、元のポインタを変更する場合:

int* inc(int* ip) { 
    return ++ip; 
} 

とその後、main中:

a = inc(a); 

それとも、のように、パラメータとしてポインタへのポインタを取り、それを元のポインタのアドレスを渡すためにincを書き換えることができます:

void inc(int** ipp) { 
    *ipp = *ipp + 1; 
} 

、次にようmainからそれを呼び出す:

運のベスト
inc(&a); 

0
ここ
void inc(int* a) { 
    a++; 

a値によって渡され、inc()内部そう変化a外反映されません。

void change(int* a) { 
    a[0] = 2; 
    a[1] = 3; 
もここ

a値によって渡されますが、あなたは何を正確に何a[0]a[1]である指しているものをa変更するaを使用することができます。

0

a++は、ローカル変数aの値を大きくします。つまり、メモリ内の次の場所にステップインします。それを増やしたい場合は、(*a)++

という表記法a[1]は、ポインタ演算を隠す構文砂糖です。これが実際に意味するものは*(a + 1)です。これには面白い副作用があります。 a[1]inc関数の場合1[a]

0

と同じものであり、それはパラメータaを変えています。 Cのすべての関数パラメータは値渡しであるため、この変更は呼び出し関数に反映されません。これと同じである

a[0] = 2; 
a[1] = 3; 

changeが呼び出されると

、それがこれを行い

*(a + 0) = 2; 
*(a + 1) = 3; 

は具体的には、ポインタaはを間接参照されています。関数はaを変更していませんが、aは何を指していますか?そのため、変更は機能の外部で表示されます。 inc

void inc(int* a) { 
    a++; 
} 

0

コードは、ポインタ値のコピーを変更し、渡されたパラメータには影響を与えません。パラメータに影響を与えるには、値ではなく参照で渡します。

void inc(int*& a) { 
    a++; 
} 
1

これはいくつかの画像を描画するのに最適な場所です。あなたは

int* a = (int*) malloc(2 * sizeof(int)); 

を書くときあなたはこのようになり、セットアップを取得:a[0]a[1]に値を割り当てた後

+---------+  +---------+---------+ 
| addr X | ---> | ????? | ????? | 
+---------+  +---------+---------+ 
pointer a 
    in main 

を、物事は次のようになります。

+---------+  +---------+---------+ 
| addr X | ---> | 1 | 2 | 
+---------+  +---------+---------+ 
pointer a 
    in main 

それでは、と仮定してみましょうinc(a)と呼んでいます。これにより、ポインタaのコピーがinc関数に渡されます。そこaという名前の2つのポインタが今しているが、彼らは同じポインタじゃないことを

+---------+  +---------+---------+ 
| addr X | ---> | 1 | 2 | 
+---------+  +---------+---------+ 
pointer a   ^
    in main    | 
         | 
+---------+   | 
| addr X |-----------+ 
+---------+ 
pointer a 
    in inc 

は予告:ポインタがコピーされる唯一のものですので、物事は今、このように見えます。ゾーイという名前の友人が2人いれば同じ名前ですが、同じ人ではありません。 incインサイド

、あなたは意味

a++; 

を書いた「それは現在を指しています1後に次のintを指すようにポインタaを進めます。」これは、次のようになります。

+---------+  +---------+---------+ 
| addr X | ---> | 1 | 2 | 
+---------+  +---------+---------+ 
pointer a     ^
    in main      | 
           | 
+---------+      | 
| addr Y |---------------------+ 
+---------+ 
pointer a 
    in inc 

そして、我々はaのコピーを操作しているので、mainaバックは、変更されていないことに気づきます。もう一度、ゾーイのアナロジーを考えてみましょう。ゾーイという名前の人と話すと、ゾーイという人と話したことになるわけではありません。ときinc戻っ結果、aのコピーは、エーテルの中に消え、そして私たちはこれを左にしている:

+---------+  +---------+---------+ 
| addr X | ---> | 1 | 2 | 
+---------+  +---------+---------+ 
pointer a 
    in main 

ポインタは変更されませんので、あなたが前とincを呼び出した後に同じ値を参照してください理由であります。

しかし、changeを呼び出す方法は異なります。あなたが最初にchangeを呼び出すと、物事は次のようになります。

+---------+  +---------+---------+ 
| addr X | ---> | 1 | 2 | 
+---------+  +---------+---------+ 
pointer a   ^
    in main    | 
         | 
+---------+   | 
| addr X |-----------+ 
+---------+ 
pointer a 
in change 

ときあなたは今、あなたが終わる場所を確認し、値を入れ、aという名前のポインタをたどる」と言ってい

a[0] = 2; 

を書きますそこ2我々は以下を参照してくださいことを意味します。a[1] = 3を書く

+---------+  +---------+---------+ 
| addr X | ---> | 2 | 2 | 
+---------+  +---------+---------+ 
pointer a   ^
    in main    | 
         | 
+---------+   | 
| addr X |-----------+ 
+---------+ 
pointer a 
in change 

も「という名前のポインタをたどる意味aの場合は、インデックス1の要素に移動し、3に置き換えます。

+---------+  +---------+---------+ 
| addr X | ---> | 2 | 3 | 
+---------+  +---------+---------+ 
pointer a   ^
    in main    | 
         | 
+---------+   | 
| addr X |-----------+ 
+---------+ 
pointer a 
in change 

さて、change戻った後、我々は戻ってmainでいる:これは次のようなります。 mainaポインタが変更されていません - それはまだ前と同じ場所で見ている - それが指し示すだという配列は、その値が変化してきました。

  • ポインタは、関数へのポインタを渡す場合、あなたはポインタのコピーの周りに渡していることを意味し、値によってCの周り渡されます。要約すると

    +---------+  +---------+---------+ 
    | addr X | ---> | 2 | 3 | 
    +---------+  +---------+---------+ 
    pointer a    
        in main    
    

  • その結果、ポインタを引数としてとる関数がポインタを指しているを変更すると、呼び出し元関数には何の効果もありません。
  • しかし、関数がを指しているものの内容をに変更すると、呼び出し元に反映されます。
関連する問題