Frage zu swap()
-
Hallo
Warum liefert folgender Code nicht das gewünschte Ergebnis? (Dass a und b vertauscht sind)
#include <stdio.h> void swap(int *,int *); int main(void) { int a,b; a=5; b=10; printf("Before:\t%d %d\n",a,b); swap(&a,&b); printf("After:\t%d %d\n",a,b); return 0; } void swap(int *x, int *y) { /* int temp; temp = *y; *y = *x; *x = temp; */ int *temp; temp = y; y = x; x = temp; }
Vielen Dank!
-
der code vertauscht nur die übergebenen pointer, aber nicht die inhalte der variablen auf die die zeigen. der auskommentierte code sieht besser aus.
-
Die Adressen von den Bezeichnern a unb b kann man nicht einfach andere Adressen zuweisen - a bzw. b stehen symbolisch für eine Feste Adresse - diese kann nicht mehr geändert werden - du kannst z. b. dem a nicht die Adresse von b geben
-
Betrachte diesen Code:
void swap(int a, int b) { int c = a; a = b; b = c; } void foo() { int x=5; int y=7; swap(x,y); /* x=5, y=7 */ }
Innerhalb von swap, (Gültigkeitsbereich von a und b) hast du den Inhalt von a und b tatsächlich getauscht, aber sobald die Funktion swap verlassen wird, gehen swap::a und swap::b ins Nirvana, foo::x und foo::y bleiben Intakt. Damit andere Funktionen den Wert von Variablen ändern können, die nicht in diesem Gültigkeitsbereich definiert sind, benutzt man Zieger. Ein Zeiger ist nur eine Varaible, die auf eine andere zeigt, sprich, der Zeiger speichert die Adresse der gezeigte Variable:
void swap(int* a, int* b) { int c = *a; *a = *b; *b = *c; } void foo() { int x=5; int y=7; swap(&x,&y); /* x=7, y=5 */ }
&x liefert die Adresse, wo x im Speicher gespeichert wird. *a = *b; ist nichts anders als "ändere den Inhalt der Speicherzelle, die von a gezeigt wird". D.h. die Änderung des Inhalts erfolgt direkt im Speicher.
void swap(int* a, int* b) { int* c = a; a = b; b = c; } void foo() { int x=5; int y=7; swap(&x,&y); /* x=5, y=7 */ }
Das hat den selben Effekt wie im ersten Beispiel. Bei a = b machst du nichts anders als "a zeige jetzt dort, worauf b zeigt", aber du hast dabei nicht den Wert geändert, worauf a gezeigt hat. Denn a=b ändert zwar den Inhalt des Zeigers, ändert aber nicht den Inhalt der Speicherzelle, auf die gezeigt wurde.
-
supertux schrieb:
void swap(int* a, int* b) { int* c = a; a = b; b = c; } void foo() { int x=5; int y=7; swap(&x,&y); /* x=5, y=7 */ }
Das ist vorallem dann eindrucksvoll, wenn man ein typedef anlegt:
typedef int* intp; void swap(intp a, intp b) { intp c = a; a = b; b = c; } void swap(int a, int b) { int c = a; a = b; b = c; }
jetzt sollte klarer sein, warum das mit den zeigern nicht so ganz will.
-
macht's doch einfach so, mit #define
#define SWAP(_a_,_b_) {(_a_)^=(_b_);(_b_)^=(_a_);(_a_)^=(_b_);} ... int a = 1234, b = 5678; SWAP(a,b); ...
ganz problemlos ohne pointer
-
net schrieb:
macht's doch einfach so, mit #define
#define SWAP(_a_,_b_) {(_a_)^=(_b_);(_b_)^=(_a_);(_a_)^=(_b_);} ... int a = 1234, b = 5678; SWAP(a,b); ...
ganz problemlos ohne pointer
struct A{}; int main() { A a; A b; SWAP(a,b); }
...
-
borg schrieb:
struct A{};
witzbold.
-
net schrieb:
ganz problemlos ohne pointer
und ganz lahm
-
Shade Of Mine schrieb:
und ganz lahm
glaub ich nicht. ist noch nicht mal ein funktionsaufruf dabei.
-
net schrieb:
glaub ich nicht. ist noch nicht mal ein funktionsaufruf dabei.
Aber der Compiler xor't sich dumm und dämlich
-
Shade Of Mine schrieb:
Aber der Compiler xor't sich dumm und dämlich
das sieht nur so aus. vs6 macht daraus
46: SWAP (a,b); 00401096 mov eax,dword ptr [ebp-4] 00401099 xor eax,dword ptr [ebp-8] 0040109C mov dword ptr [ebp-4],eax 0040109F mov ecx,dword ptr [ebp-8] 004010A2 xor ecx,dword ptr [ebp-4] 004010A5 mov dword ptr [ebp-8],ecx 004010A8 mov edx,dword ptr [ebp-4] 004010AB xor edx,dword ptr [ebp-8] 004010AE mov dword ptr [ebp-4],edx
nur 3 xor's, die mov's überwiegen
aber als funktion entsteht sowas:36: void swap (int *a, int *b) 37: { 00401020 push ebp 00401021 mov ebp,esp 00401023 sub esp,44h 00401026 push ebx 00401027 push esi 00401028 push edi 00401029 lea edi,[ebp-44h] 0040102C mov ecx,11h 00401031 mov eax,0CCCCCCCCh 00401036 rep stos dword ptr [edi] 38: int tmp = *a; 00401038 mov eax,dword ptr [ebp+8] 0040103B mov ecx,dword ptr [eax] 0040103D mov dword ptr [ebp-4],ecx 39: *a = *b; 00401040 mov edx,dword ptr [ebp+8] 00401043 mov eax,dword ptr [ebp+0Ch] 00401046 mov ecx,dword ptr [eax] 00401048 mov dword ptr [edx],ecx 40: *b = tmp; 0040104A mov edx,dword ptr [ebp+0Ch] 0040104D mov eax,dword ptr [ebp-4] 00401050 mov dword ptr [edx],eax 41: } 00401052 pop edi 00401053 pop esi 00401054 pop ebx 00401055 mov esp,ebp 00401057 pop ebp 00401058 ret
wobei noch der eigentliche aufruf hinzu kommt. da bezweifle ich immer noch, dass das makro lahmer ist.
-
Nur weil das eine kürzer ist, als das andere, sagt das noch lange nichts über die Geschwindigkeit aus. Nicht die Summe der Befehle ist entscheidend, sondern die Dauer für einen Befehl.