2016-06-05 8 views
0

Ich versuche, den Unterschied zwischen Pass von Wert und übergeben durch Bezugnahme zu verstehen, und ich dachte, dass ich es endlich verstehen, bis ich diesen Code sah:Warum ist das ein Wert?

void change(char *p1) 

{ 
    p1="new"; 
} 

int main() 

{ 
    char *txt1=(char*)malloc(200*sizeof(char)); 

    txt1="original"; 
    printf("before :%s\n",txt1); 
    change(txt1); 
    printf("after :%s\n",txt1); 

} 

Ist es nicht eine Adresse vorbei? und dann änderst du es und zeigst es woanders hin?

Die Ausgabe lautet:

vor: Original

nach: original

Warum ist das so?

+2

Technisch C unterstützt nicht alles, aber nach Wert übergeben. –

+0

@JoachimPileborg: "Technisch"? In welchem ​​Aspekt unterstützt Pass-by-Reference mehr als jede andere Turing-Complete-Sprache? – Olaf

+0

C, C++, Java und jede Sprache, von der ich je gehört habe, gehen nach Wert. Aber Sie können Verweise (oder Zeiger) nach Wert übergeben, was es ein wenig verwirrend macht. – alain

Antwort

2

Es gibt keine Pass-by-reference in C. Funktionsparameter übergeben werden, mit Pass-by-Wert. Das heißt, p1 selbst wird nach Wert übergeben. Sie können den Inhalt der Speicheradresse, auf die p1 (*p1) zeigt, von der aufgerufenen Funktion und nicht von p1 selbst ändern.

Um den Inhalt einer Variablen var zu ändern, müssen Sie die Adresse var übergeben, also, wenn Sie einen Zeiger selbst ändern möchten, müssen Sie die Adresse des Zeigers an die Funktion übergeben.

Das sagte please see this discussion on why not to cast the return value of malloc() and family in C.

2

Dies ist die Übergabe einer Adresse als Wert. Damit der Aufrufer die lokale Variable des Aufrufers ändert, übergeben Sie die Adresse , was geändert werden soll.

#include <stdio.h> 

void change(char **p1) 

{ 
    *p1="new"; 
} 

int main(void) 

{ 
    char *txt1; /* no causing memory leak */ 

    txt1="original"; 
    printf("before :%s\n",txt1); 
    change(&txt1); 
    printf("after :%s\n",txt1); 

} 
1

Im Funktionsaufruf change(txt1); wird txt1 als Wert übergeben. Es wird in den Parameter der Funktion change kopiert. Dies zeigt pi Punkte auf die gleiche Zeichenfolge wie txt1 zeigt auf. Wenn eine neue Zeichenfolge p1 zugewiesen wird, wird p1 geändert, um auf diese Zeichenfolge zu zeigen, während txt1 auf die vorherige verweist.

ist dieser Fall sehr ähnlich wie

char *s1 = "String"; 
char *s2 = s1;  // Both s1 and s2 points to same string 
s2 = "Another string" // Now s2 points to "Another string" while s1 pointing to "String". 

Außer, dass Sie Ihren Code Speicherverlust verursacht. Es sollte wie

char *txt1=(char*)malloc(200*sizeof(char)); 
strcpy(txt1,"original"); 
1

Pass By Reference und Pass von Wert. Pass By Reference and Pass By value.

+0

Hahahaaa ............... Brilliant.: D – haccks

+0

Außer, dass es so etwas wie "pass by reference" in C nicht gibt. (-: – user3078414

+0

) Ich habe versucht, das Konzept zu definieren ;) –

1

Hier ist ein Beispiel, das ich zuvor verwendet habe. Es sei angenommen, die folgenden zwei Funktionen:

void foo(T *p) // where T is an arbitrary data type 
{ 
    *p = new_value(); // write new value to the thing p points to 
} 

void bar(void) 
{ 
    T var; 
    foo(&var); // write new value to var 
} 

Für Funktion foo den Inhalt var (ein Objekt vom Typ T) aktualisieren wir einen Zeiger auf var (Typen T *) passieren müssen.

Wenn wir T mit einem Zeigertyp P * ersetzen, dann wird der obige Code wird

void foo(P **p) 
{ 
    *p = new_value(); // write new value to the thing p points to 
} 

void bar(void) 
{ 
    P *var; 
    foo(&var); // write new value to var 
} 

Die Semantik ist genau die gleiche; wir wollen foo einen neuen Wert zu var schreiben, so übergeben wir einen Zeiger auf var. Es ist nur, dass in diesem Fall var bereits ein Zeigertyp ist, so dass wir einen Zeiger auf einen Zeiger übergeben. ein weiteres Dereferenzierungsebene immer als die Art der var

Grundsätzlich für foo den Inhalt var zu aktualisieren, müssen Sie den Ausdruck&var als Argument, dh die Art der formalen Parameter übergeben p wird.

Type of var  Type of &var  Type of p 
-----------  ------------  --------- 
      T    T *   T * 
     T *    T **   T ** 
     T **    T ***   T *** 

usw.