# Wo ist das Problem bei dieser einfachen Funktion?



## ElMadridano (1. Okt 2018)

Hallo,
ich bin ein ziemlicher Anfänger bei der C Programmierung. Eigentlich hatte es ziemlich gut geklappt, bis die Funktionen dran kamen. Diese wollte ich jetzt üben und hab mir irgendwelche Aufgaben ausgedacht. 
Diese hier z.B

```
int Function1(int a)
{
    int Rueckgabewert;
    printf("Zahl1:");
    scanf("%i", &a);
    return Rueckgabewert;
}
int Function2(int b)
{
    int Rueckgabewert;
    printf("Zahl2:");
    scanf("%i", &b);
    return Rueckgabewert;
}
int Function3(int a, int b)
{
    int Rueckgabewert;
    Rueckgabewert=a+b;
    return Rueckgabewert;
}
int main ()
{
    int Zahl1;
    int Zahl2;
    int Result;
    Function1(Zahl1);
    Function2(Zahl2);
    Result=Function3(Zahl1, Zahl2);
    printf("Resultat:%i", Result);
}
```
Dieses Programm soll 2 Zahlen in 2 Funktionen einlesen und dann diese beiden Zahlen in der 3. Funktion summieren. Wenn ich das aber Compiliere, funktioniert erstmal alles soweit, nur das dann immer das Resultat 148 angezeigt wird. Und das versteh ich einfach nicht. Hab ich vllt. die Zahlen von den Funktionen 1 und 2 falsch an die Funktion 3 übergeben? Wie muss es richtig sein?

Ich hoffe das mir weitergeholfen werden kann, Danke


----------



## Robat (1. Okt 2018)

Das a aus der Function1 hat nichts mit Zahl1 aus der main() zu tun. So wie du es jetzt hast würde nur der Wert von Zahl1 kopiert werden und Function1 übergeben werden. 
Function1 sollte eher ein Pointer auf einen int erwarten (*-Operator) und es müsste die Adresse von Zahl1 an diese Funktion übergeben werden (&-Operator). 

```
void Function1(int* a) {
    scanf("%d", a);
}
int main() {
    int Zahl1;
    Function1(&Zahl1);
}
```
Das ganze solltest du anlog zu Zahl2 machen. Gibt es denn einen Grund, dass du jeder Funktion einen Rückgabewert gibst ohne ihn zu benutzen?


----------



## ElMadridano (1. Okt 2018)

Robat hat gesagt.:


> Das a aus der Function1 hat nichts mit Zahl1 aus der main() zu tun. So wie du es jetzt hast würde nur der Wert von Zahl1 kopiert werden und Function1 übergeben werden.
> Function1 sollte eher ein Pointer auf einen int erwarten (*-Operator) und es müsste die Adresse von Zahl1 an diese Funktion übergeben werden (&-Operator). Das ganze solltest du anlog zu Zahl2 machen. Gibt es denn einen Grund, dass du jeder Funktion einen Rückgabewert gibst ohne ihn zu benutzen?



Pointer wäre erst mein nächstes Thema. Ich wollte jetzt erstmal Funktionen richtig verstehen. Was ich mit dem a machen wollte ist, das Zahl1 vom Main in die Funktion1 zu übergeben, damit ich nicht eine neue Variable deklarieren wollte. Dann wollte ich ein Wert für a einscannen und dieses dann wieder zurück in das Main Programm übergeben. Danach sollte es vom Main zu Function3 übergeben werden, damit ich dort mit dem a arbeiten könnte. 
Um Variablen vom Main in andere Funktionen zu übergeben muss ich es doch in den Funktionsprototypen reinschreiben, oder? Wie geht es denn richtig ohne erstmal Pointer zu verwenden?


----------



## Robat (1. Okt 2018)

ElMadridano hat gesagt.:


> Um Variablen vom Main in andere Funktionen zu übergeben muss ich es doch in den Funktionsprototypen reinschreiben, oder?


Das ist an sich richtig. Allerdings unterscheidet man hier zwischen Call-By-Value und Call-By-Reference.
Call-By-Value bedeutet, dass innerhalb der aufgerufenen Funktion mit der Kopie der übergebenen Variable gearbeitet wird und sich somit die Änderungen nicht auf den ursprünglichen Wert auswirken
Call-By-Reference hingegen bewirkt, dass sich Änderungen auf die ursprünglichen Werte auswirken, da hier nicht die Kopie des Wertes übergeben wird sondern dessen Adresse im Speicher.

Deine Werteparameter der Methoden sind momentan alle Call-By-Value. Das heißt im Klartext, dass nur der Wert von Zahl1/Zahl2 kopiert werden und an die Function1/Function2 übergeben werden - es ändert sich aber nichts an Variablen. Das ist auch der Grund, warum du an Pointern nicht vorbei kommen wirst, wenn du es unbedingt so machen willst.

Eine Alternative wäre, der Methode keine Parameter zu geben und die eingescannten Wert aus der Methode heraus zurückzugeben. So bräuchtest du nicht zwingend Pointer

```
int Function1() {
    int a = 0;
    scanf("%d", &a);
    return a;
}
```


----------



## ElMadridano (1. Okt 2018)

Danke für die Super Erklärung. Damit ergibt alles einen Sinn und mein Programm funktioniert jetzt auch.

```
int Function1()
{
    int a;
    printf("Zahl1:");
    scanf("%i", &a);
    return a;
}
int Function2()
{
    int b;
    printf("Zahl2:");
    scanf("%i", &b);
    return b;
}
int Function3(int Zahl1, int Zahl2)
{
    int Rueckgabewert;
    Rueckgabewert=Zahl1+Zahl2;
    return Rueckgabewert;
}
int main ()
{
    int Zahl1;
    int Zahl2;
    int Result;
    Zahl1=Function1(Zahl1);
    Zahl2=Function2(Zahl2);
    Result=Function3(Zahl1, Zahl2);
    printf("Resultat:%i", Result);
}
```
Jetzt will ich versuchen das selbe Programm mit Pointern zu programmieren.


----------



## Robat (1. Okt 2018)

Mach das. Dabei kannst du dir ja mal überlegen ob es Sinn hat, wirklich 2 Funktionen für die Eingabe zu schreiben. Machen nicht beide Funktionen (Function1() und Function2() ) das gleiche abgesehen von der String-Ausgabe?


----------



## ElMadridano (3. Okt 2018)

Hallo,
Ich hab eine neue Frage. Wollte jetzt extra dafür kein neues Thread aufmachen. 
Ich wollte mir ein paar Grundlagen Wissen über Pointer und Array aneignen, da bin ich auf folgende Aufgabe gestoßen, wo das Programm schon gegeben ist:

```
int main()
{
    int *IntZeiger = NULL;
    int IntArray[5];      

    IntZeiger = IntArray; 
    IntArray[0] = 5;
    IntArray[1] = 4;
}
```

Die letzten beiden Zeilen soll ich so abändern, dass die Änderungen der Feldelemente mittels des Zeigers
IntZeiger geschehen. Bei dem Programm hab als erstens ich nicht verstanden, was dieses NULL am Anfang bedeutet. Was ist das und seit wann kann man Zeichen an einer Int Variable setzen? 
Meine 2.Frage: In der 3.Zeile steht "IntZeiger = IntArray", was bedeutet IntArray und wo sind die Eckigen Klammern die man bei einem Array braucht? 
Und als letztens weiß ich nicht, wie ich die Aufgabe lösen soll, Tipps wären sehr hilfreich.
Danke


----------



## temi (3. Okt 2018)

Es handelt sich um einen Zeiger, der sozusagen ins Nichts zeigt: Nullpointer.
http://www.cplusplus.com/reference/cstring/NULL/


----------



## ElMadridano (3. Okt 2018)

ok danke schonmal dafür, 
und was heißt das hier:  IntZeiger = IntArray; ?
Außerdem, wie ist die Aufgabe zu lösen, dass die Änderungen des Arrays der Feldelemente mittels des Zeigers
IntZeiger geschehen?

Danke


----------



## temi (3. Okt 2018)

Keine Ahnung nach welcher Vorlage oder Buch du lernst, aber anscheinend taugt es nicht. Das sind doch Grundlagen, die behandelt sein müssten, bevor man diese Aufgabe zu lösen versucht.


----------



## ElMadridano (3. Okt 2018)

Es ist ein script von der Uni und ich bin auch nicht so lange dabei. Die Grundlagen sollte ich anhand solcher Aufgaben lernen. Ich würde mich über Tipps freuen.


----------



## temi (3. Okt 2018)

ElMadridano hat gesagt.:


> Die Grundlagen sollte ich anhand solcher Aufgaben lernen. Ich würde mich über Tipps freuen.


Man kann keine Grundlagen lernen, indem man Aufgaben löst, von deren Grundlagen man keine Ahnung hat und dann versucht sich eine fertige Lösung zu beschaffen.

Irgendwo in dem Script muss ja etwas über Zeiger, Definition und Deklaration von Zeigervariablen, C-Arrays und Zeigerarithmetik stehen.


----------



## ElMadridano (3. Okt 2018)

Die Sachen stehen da drin, aber nichts mit C-Arrays. Über Arrrays und Pointer kannte ich mich schon etwas aus, nur wusste ich nicht wie ich die beiden Sachen verbinden soll. Aber durch eigene Recherche hab ich rausgefunden, was  " IntZeiger = IntArray" bedeutet. Nämlich wird dem 1.Feld im Array dieser Pointer zugewiesen. Und wenn man dann den 2.Feld im Array haben möchte muss man IntZeiger++ schreiben und für jede weitere dann IntZeiger=IntArrray +2 oder +3 und so weiter.
Jetzt weiß ich aber nicht, wie ich in den Pointer was Reinschreiben, welches dann vom Array übernommen wird.
Tipps reichen mir schon, darüber würde ich mich freuen,
Danke


----------



## mrBrown (3. Okt 2018)

ElMadridano hat gesagt.:


> Aber durch eigene Recherche hab ich rausgefunden, was " IntZeiger = IntArray" bedeutet. Nämlich wird dem 1.Feld im Array dieser Pointer zugewiesen.


Nein.
IntZeiger wird die Adresse des Arrays (was gleichzeitig die Adresse des ersten Elements ist) zugewiesen.
Das Array wird da nicht verändert.


----------



## ElMadridano (3. Okt 2018)

Jawoll alles klar danke, Aufgabe gelöst


----------



## mrBrown (3. Okt 2018)

Lässt du uns an der Lösung teilhaben?


----------



## ElMadridano (3. Okt 2018)

Oh ja stimmt, wie unhöflich von mir

```
int main()
{
    int *IntZeiger=NULL;
    int IntArray[5];

    IntZeiger=IntArray;
    *IntZeiger=5;
    *(IntZeiger+1)=4;
    printf("Wert im Feld 1 ist %i\n", IntArray[0]);
    printf("Wert im Feld 2 ist %i\n", IntArray[1]);
}
```
Über Meinungen und weitere Tipps würde ich mich freuen,
Danke


----------



## mrBrown (3. Okt 2018)

Du kannst auch beim Zugriff über den Pointer die Schreibweise mit Klammern nutzen: `IntZeiger[0]=5;`


----------



## ElMadridano (3. Okt 2018)

Geiler Tipp Danke

```
int *IntZeiger=NULL;
    int IntArray[5];
    IntZeiger=IntArray;
    IntZeiger[0]=5;
    IntZeiger[1]=4;
    printf("Wert im Feld 1 ist %i\n", IntArray[0]);
    printf("Wert im Feld 2 ist %i\n", IntArray[1]);
```


----------



## mihe7 (3. Okt 2018)

@ElMadridano schau Dir mal http://www.cplusplus.com/doc/tutorial/pointers/ an, da sollte etwas für Dich dabei sein


----------

