001
10.02.2003, 20:47 Uhr
virtual
Sexiest Bit alive (Operator)
|
Nein, der Code ist nicht korrekt, weil char string[250] Eine lokale Variable ist, die nach verlassen der Routine nicht mehr existiert und überschrieben wird. Daher zeigt der Rückgabewert nach nirgendwo. Dir dürfte Klar sein, daß sich in solchen Fällen C++ ganz gut macht, denn die Klasse std::string erledigt das Speicherhandling für dich. Wenn es aber doch C sein soll, hast Du im Wesentlichen drei Möglichkeiten:
1. Verwenden einer statischen Variable Das sähe so aus:
C++: |
onst char* get_string(int a) { if(a==1) { [b]static[/b] char string[250] = "Hello World"; return string; }
return NULL; }
|
Dieser Code ist korrekt, weil das "static" bewirkt, daß die lokale Variable auch nach dem Funktionsaufruf bestehen bleibt. Tatsächlich wirst Du in der einen oder anderen API solche Routinen finden, die genauso vorgehen. Der Nachteil ist natürlich, daß es diese Variable einmal gibt; dh wenn der String bei unterschiedlichen a's unterschiedliche Werte zurückgeben soll, wird string immer wieder überschrieben. Folgender Code illustriert das Problem:
C++: |
const char* func(int x) { static char buffer[100]; switch (x) { case 1: strcpy(buffer, "eins"); break; case 2: strcpy(buffer, "zwei"); break; default: strcpy(buffer, "Soweit kann ich noch nicht zählen!"); break; } return buffer; }
int main() { const char* p1; const char* p2;
p1 = func(1); p2 = func(2);
printf("func(1) ergibt: %s\n", p1); printf("func(2) ergibt: %s\n", p2); }
|
Der Vorteil ist, daß man sich einen Dreck ums Speicherhandling kümmern muß. 2. Dynamischer Speicher Man kann es auch mit dynamischen Speicher machen, dann sieht deine Routine so aus:
C++: |
const char* get_string(int a) { if(a==1) { char* buffer; buffer = malloc(strlen("Hello World!")+1); if (buffer) strcpy(buffer, "Hello World!"); return buffer; } return NULL; }
|
Dieser Ansatz merzt zwar den Nachteil des Überschreibens vorheriger Funktionsergebnisse aus, hat aber den Nachteil, daß der Aufrufer dafür sorgen muß, daß der Speicher freigegeben wird, Der Aufrufer muß free() für das Funktionsergebnis aufrufen. Ein weiterer nachteil ist, daß man wenn die Rückgabe NULL ist, eigentlich nicht recht weiß, ob a!=1 war oder aber einfach kein Speicher vorhanden war (dh. der Aufrufer sollte errno==ENOMEM abfragen). 3. Aufrufer == Speichereigner Dann gibt es natürlich auf die Möglichkeit, daß der Aufrufer eigentümer des Speichers ist und der Funktion mitteilt, wo und wie viel Speicher für das Ergebnis da ist:
C++: |
const char* get_string(int a, char* ergebnis_buffer, int max_len) { if(a==1) { if (strlen("Hello World")>=max_len) { /* Fehler: Rückgabebuffer zu klein */ return NULL; } strcpy(ergebnis_buffer, "Hello World!"); return ergebnis_buffer; } return NULL; }
|
Zwar hat man mit diesem Ansatz auch vermutlich weniger Trouble mit Speicherhandling (zeit jedenfalls die Erfahrung), aber erstens ist der Funktionsaufruf ungleich komplizierter und zweitens kann man wieder nicht entscheiden: ist a!=1 oder aber der buffer einfach zu klein, wenn NULL zurück kommt. -- Gruß, virtual Quote of the Month Ich eß' nur was ein Gesicht hat (Creme 21) Dieser Post wurde am 10.02.2003 um 20:47 Uhr von virtual editiert. |