Übergabe einer Variable an nächste Funktion?!

Hallo zusammen,

folgendes Problem plagt mich gerade. Ich würde gerne einen in einer Funktion test() definierte Variable ‚char x =4‘ in meiner Hauptfunktion ‚main()‘ aufrufen und ausdrucken.

Dafür hatte ich ursprünglich 3 Mgl.

  1. Globale Variablen deklarieren und darüber die Werte weitergeben
    (unschön!!)
  2. Über den Rückgabewert ‚return‘ arbeiten
  3. Per Pointer auf den Wert der Variable zeigen.

Unten habe ich meine ursprüngliche Version zu Mgl2. Jedoch würde ich am liebsten die 3. Mgl anwenden da die Daten der Variablen aus ‚test()‘ über eine SQL-Abfrage eingelesen werden und der Pointer die sauberste Lsg ist.

Würde mich freuen, wenn mir jemand helfen könnte.

/********************************************************************/
#include

/* Deklaration der Funktion test() */
int test(char x);

/* Hauptfunktion main() */
int main() {

/* initialisiere den Wert c */
char c = 1;

/* Ausgabe des Rückgabewertes aus der Funktion test() */
printf("\n%d ist mein Uebergabewert\n", test©);

return 0;
}

/* Zusatzfunktion test() mit Variable als Rückgabewert */
int test(char a) {

/* den Wert 4 möchte ich in meiner main() wieder aufrufen und ausgeben können */
char x = 4;
return x;
}

/********************************************************************/

Hallo,

#include

/* Deklaration der Funktion test() */
int test(char x);

/* Hauptfunktion main() */
int main() {

/* initialisiere den Wert c */
char c = 1;

/* Ausgabe des Rückgabewertes aus der Funktion test()
*/
printf("\n%d ist mein Uebergabewert\n", test©);

return 0;
}

/* Zusatzfunktion test() mit Variable als Rückgabewert
*/
int test(char a) {

/* den Wert 4 möchte ich in meiner main() wieder
aufrufen und ausgeben können */
char x = 4;
return x;
}

/********************************************************************/

Deine Funktion Test macht gar nichts. Du könntest genauso direkt eine 4 ausgeben. Vielleicht solltest Du den Parameter „a“ für irgendwas benutzen?

int test(char a){
 int x=0;

 if (a==4)
 x = 4;

 return x;
}

Wenn Du immer nur auf „4“ oder „nicht 4“ testen willst, dann kannst Du Dir auch die ganze Funktion sparen und das über ein einfaches „if“ neim einlesen abfangen.

Gruß

Fritze

  1. Über den Rückgabewert ‚return‘ arbeiten

Was gefällt dir daran nicht? Wenn es nur um den Wert einer Variablen zu einem konkreten Zeitpunkt geht, ist dies die „sauberste Lösung“.

Servus
Tom

Bin nicht sicher, ob es das ist, was du wolltest…

Hallo zusammen,

folgendes Problem plagt mich gerade. Ich würde gerne einen in
einer Funktion test() definierte Variable ‚char x =4‘ in
meiner Hauptfunktion ‚main()‘ aufrufen und ausdrucken.

Hallo Matthias,
ich verstehe Deinen Lösungsansatz nicht wirklich. Was spricht denn dagegen mit einem return-Wert zu arbeiten?
Aber egal. Ich versuche Zeiger, wenn möglich, zu vermeiden. Bei Zeigern schleichen sich leicht Fehler ein. Vielleicht täte es bei Dir ja auch eine Referenz?

Wie auch immer. Drei Lösungen:

**A) mit Referenzvariablen

void test(char c, char& x)
{
// Was auch immer Du hier mit ‚c‘ vorhast, …tu es.
x = 4;
return;
}
‚char&‘ bedeutet, dass test() keine Kopie der Variablen übergeben wird, sondern ein Verweis auf diese Variable. test() hat also Zugriff auf diese Variable. Das gute daran: Die Syntax in der Funktion ist dieselbe, wie mit einer Kopie der Variablen. Und es ist sicherer als Zeiger: Eine Referenz kann nie auf einen ungültigen Speicherbereich zeigen.

int main()
{
char c, x;
c = 1;
test(c, x);
printf("\n%d ist dein Uebergabewert\n", (int)x);
return 0;
}

**B) mit Zeiger

void test(char c, char* x)
{
*x = 4; // !
return;
}

int main()
{
char c, *x;
x = new char; // !
if (x != NULL)
{
test(c, x);
printf(("\n%d ist dein Uebergabewert\n", (int)(*x)); // !
}
delete x; // sonst Speicherleck
return 0;
}

**C) mit wirklich in test() initialisierter Variablen.
Warum das nötig ist, verstehe ich nicht. Aber Du wirst schon gute Gründe haben.

void test(char c, char* x)
{
x = new char;
if (x != NULL)
{
*x = 4; // nur, falls new-Operator Speicher reservieren konnte
}
return;
}

Problem bei diesem Ansatz: Du mußt höllisch aufpassen, dass kein Speicherleck entsteht. Vor allem, da Du die Funktion ja sicherlich mehrmals aufrufen wirst.

int main()
{
char c, *x;
c = 1;
x = NULL; // Zeiger immer erstmal mit NULL initialiseren…
test(c, x);
if (x != NULL) // …das ist sicherer
{
printf(…wie in B) );
}
delete x; // immer vor jedem neuen Aufruf von test()
test(c, x);

return 0;
}

Gruß,
Bernhard.

entweder macht man c oder cpp, aber nicht beides in einem :wink:

1 Like

Hallo Bernhard,

erstmal tausend Dank für die schnelle, ausführliche und sehr gut kommentierte Antwort.

Ich benötige den Übertrag einer Variable in ‚c‘, da ich wie bereits erwähnt in einer Funktion einen char-Wert (und auch einen struct) aus einer SQL-Tabelle auslese. Da ich in der nächsten Funktion von den ausgelesenen Werten des char (genauso wie des struct, deswegen der Pointer) Gebrauch mache, würde ich wohl eher die Pointerlösung bevorzugen müssen.

Doch was müßte ich ändern, wenn der char-Wert nicht ‚4‘ sondern beispielsweise ‚Uebertrag‘ beinhaltet.

Kann ich das so überhaupt angehen oder muß ich da auf eine andere Lösung zugreifen??

Hab unten nochmal Dein Beispiel reingesetzt mit meinem Wunsch dass er jetzt statt 4 Uebertrag weitergibt.

*x = ‚Uebertrag‘; // !!!

/********************** Lösung mit Pointer ***************************/

void test(char* x)
{
*x = ‚Uebertrag‘; // !!!
return;
}

int main()
{
char *x;
x = new char; // !
if (x != NULL)
{
test(x);
printf("\n%d ist dein Uebergabewert\n", (int)(*x)); // !
}
delete x; // sonst Speicherleck
return 0;
}

Auch Dir erstmal many thanxx fürs schnelle Antworten. Ich weiß auch noch nicht. Ich dachte eben mit Pointern habe ich da ebenso eine saubere Lösung.

Viele Grüße aus Stuttgart

Mathias

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Deine Funktion Test macht gar nichts. Du könntest genauso
direkt eine 4 ausgeben. Vielleicht solltest Du den Parameter
„a“ für irgendwas benutzen?

int test(char a){
int x=0;

if (a==4)
x = 4;

return x;
}

Wenn Du immer nur auf „4“ oder „nicht 4“ testen willst, dann
kannst Du Dir auch die ganze Funktion sparen und das über ein
einfaches „if“ neim einlesen abfangen.

Gruß

Fritze

Hallo Fritze,

auch Dir erstmals vielen Dank für die schnelle Antwort. Ich denke mein Problem liegt darin dass ich in meiner ersten Funktion einen recht komplexen Abruf einer SQL-Tabelle mache. ich habe in meinem Beispiel jedoch versucht auf den Punkt zu kommen und nicht den ganzen unnötigen funktionierenden Schmuh abzubilden.

Mein Kernproblem besteht darin dass ich einen char-Wert (Bsp char x[20] ; x = ‚Eingabe‘) in einer weiteren Funktion aufrufen möchte.

Deswegen der Gedanke mit dem Pointer

Grüße aus Stuttgart

Mathias

Hallo Bernhard,

Ich benötige den Übertrag einer Variable in ‚c‘, da ich wie
bereits erwähnt in einer Funktion einen char-Wert (und auch
einen struct) aus einer SQL-Tabelle auslese. Da ich in der
nächsten Funktion von den ausgelesenen Werten des char
(genauso wie des struct, deswegen der Pointer) Gebrauch mache,
würde ich wohl eher die Pointerlösung bevorzugen müssen.

Doch was müßte ich ändern, wenn der char-Wert nicht '4’
sondern beispielsweise ‚Uebertrag‘ beinhaltet.

*x = ‚Uebertrag‘; // !!!

Hi Matthias.
Okay, wenn ich dich richtig verstehe, dann musst du einen String übergeben. Wenn Du das in C machen willst, und nicht in C++, dann hast Du gleich einen ganzen Sack von Schwierigkeiten am Hals.

Ein String in C ist einfach ein Zeiger auf char. Deklaration: ‚char *str;‘ Das ‚*‘ gehört zur Variable, nicht zum Typnamen. Würdest du ‚char* str1, str2‘ schreiben, wäre nur ‚str1‘ ein Zeiger, ‚str2‘ ein char.
Guck mal im Internet in irgendwelchen C/C++ Tutorials was ein Zeiger ist. Hier nur soviel: Wenn Du ‚char *str;‘ schreibst, dann weiß Dein Compiler, dass in str die Adresse des Beginns eines Speicherbereichs liegt. Und er weiß, dass in diesem Speicherbereich char-Werte hintereinander abgelegt sind. Das ist leider auch alles. Er weiß nicht, wie viele dort abgelegt sind, oder ob die Adresse überhaupt auf einen reservierten Speicherbereich verweist. Darum mußt Du dich kümmern.
Die Konvention für C-Strings ist, dass das Ende des Strings durch das Nullterminierungszeichen ‚\0‘ angezeigt wird.

Die erste Entscheidung, die du treffen mußt, ist, ob du das Ergebnis aus deiner SQL-Abfrage flach kopieren kannst, oder ob du es tief kopieren mußt. Ich nehme mal an, dass deine SQL-Abfrage einen C-String zurückliefert.

Flaches Kopieren:
char *sql_uebergabe, *sql_result;
sql_ubergabe = sql_result;
// sql_uebergabe verweist jetzt auf denselben Speicherbereich wie sql_result. Nicht der String, sondern die Adresse des Strings wurde kopiert!

Tiefes Kopieren:
#include „string.h“;
strcpy (sql_uebergabe, sql_result);
// Der String sql_result wird in den Speicherbereich kopiert, auf den sql_uebergabe verweist. Du hast jetzt zwei Strings, einen in sql_uebergabe, einen in sql_result. Nullterminierungszeichen wird von stcpy(char*, char*) mitkopiert.
Alles klar?

Die zweite Schwierigkeit ist, dass du vielleicht nicht weißt, wie lang der String ist. Wenn Du die maximale Länge kennst, dann wäre das gut.

Kennst du die maximale Länge dann deklarierst du einfach ein Array:
char sql[Länge des Strings + 1]; // + 1 für das Nullterminierungszeichen

sql ist damit automatisch vom Typ char*. Und sql verweist auf einen Speicherbereich für den ein Bereich im Umfang von [Länge des Strings + 1] reserviert wurde.
Wenn du auf ein Element des Arrays zugreifst, z.B. ‚sql[2]‘, dann übersetzt der Compiler das in ‚*(sql + 2)‘.
Wie gesagt, informier Dich im Intenet über Zeiger.

Kennst Du die maximale Länge nicht, dann mußt Du den Speicherbereich auf den ‚sql‘ verweist, dynamisch reservieren.
Dafür gibt es in C die Funktionen malloc() und free(), in C++ die Operatoren new und delete.

char *sql;
sql = (char*) malloc(‚Länge des Strings + 1‘ * sizeof(char));
Die Funktion malloc reserviert einen Speicherbereich mit der Größe, die ihr übergeben wird. Angenommen dein String ist 20 Zeichen lang, dann schreibst Du:
malloc(21 * sizeof(char));
sizeof() liefert die Größe eines Typs zurück. Bei char ist sie 1. Du könntest also auch schreiben: malloc(21). Ist aber nicht zu empfehlen.
Malloc übergibt eien void-Zeiger auf die Adresse des Speicherbereichs, den sie reserviert hat. Deswegen mußt du diesen Zeiger in einen Zeiger auf char umwandeln. Daher das ‚(char*) malloc(…)‘

Mit ‚free(sql)‘ gibtst Du den Speicherbereich dann frei, wenn Du ihn nicht mehr brauchst.

Übrigens in beiden Fällen sieht die Funktionsschnittstelle von test() gleich aus:
void test(char c, char* sql);

Aber Vorsicht! Zeiger sind nicht einfach zu handhaben. Nimm Dir ruhig die Zeit, im Internet oder in einem Buch zu stöbern. Es lohnt sich.

Gruß,
Bernhard.

P.S.:
*x = ‚Ubertrag‘; // funktioniert nicht!
Wenn Dein Compiler das überhaupt schlucken sollte, dann steht in *char
nur ‚U‘.
Besser:
*x = „Uebertrag“; // aber nicht vergessen, vorher Speicher reservieren.

1 Like

Übergabe einer Variable an nächste Funktion?!
Hallo Benhard,

nochmals vielen Dank für die schnelle und passende Antwort. Bin gerade dabei mir das alles so hinzubiegen, dass es auf mein Bsp. hinhaut.

Werde dann am Montag oder Dienstag vorraussichtlich das komplette Konstrukt mal reinstellen, falls es dann mal jemand gebrauchen kann.

Ausserdem habe ich jetzt inzwischen das Ganze in einen struct eingelesen.

Vielen Dank und schönes Wochenende

Mathias

Stringübergabe in einem simplen Beispiel?!?!
Hallo Bernhard,

also die SQL-Abfrage leifert einen C-String zurück. Ich muß die SAche tief kopieren.
Ich habs versucht aber könntest Du (oder jemand anderes) mir vielleicht das Ganze in ein simples Beispiel packen?? Wär spitze und eine unendliche Hilfe. Komm nämlich so nicht weiter und hab auch schon alles im Internet und Buchmaterial abgegrast.

Merci schon mal im Voraus…

Grüße

Mathias

Korrektur: Zwei Böcke geschossen.

Hallo Bernhard,

also die SQL-Abfrage leifert einen C-String zurück. Ich muß
die SAche tief kopieren.
Ich habs versucht aber könntest Du (oder jemand anderes) mir
vielleicht das Ganze in ein simples Beispiel packen?? Komm nämlich so nicht weiter.

Hi Mathias,
das könnte an meiner Antwort liegen. Ich habe nämlich zwei Böcke geschossen. Sorry, aber mit Zeigern auf char arbeite ich sehr selten.
Ein Beispiel habe ich dir persönlich zugemailt. Das ist glaube ich besser so. Ich habs getestet. Es funktioniert.

Also hier die zwei Korrekturen:

Erstens:
char *str;
*str = „Das funktioniert leider nicht.“;
besser ist
str = „Das funktioniert.“;
String-Literale sind die einzigen Literale, für die der Compiler Speicher reserviert. Was hier passiert, ist, dass in str die Adresse kopiert wird, in der das String-Literal „Das funktioniert.“ steht.

Zweitens:
Die Funktionsschnittstelle muss lauten:
void test(char* c, char** uebernommen);
char** ist ein Zeiger auf einen Zeiger auf char. Klar?
Der Aufruf muss lauten:
char *zuUebergeben;
test(c, &zuUebergeben);
Hier wird der Funktion die Adresse uebergeben, in der der Zeiger auf char selbst steht. ‚uebernommen‘ zeigt danach auf den Zeiger auf char. Innerhalb der Funktion muss ‚uebernommen‘ deshalb immer einmal dereferenziert werden, um Zugriff auf ‚zuUebergeben‘ zu erhalten.
zum Beispiel:
char *kopie;
kopie = (char*) malloc(100);
strcpy(*uebernommen, kopie);

tschuldigung nochmals,
Bernhard.

1 Like