Hey Leute, ich habe folgende Aufgabe in der Schule nicht verstanden, ich
hoffe ihr könnt mir helfen, da ich gerade für eine Klausur lerne.
Ich habe folgenden Code gegeben und soll bestimmen, was das Endergebnis
ist,das auf dem Bildschirm angezeigt wird:
1
#include<stdio.h>
2
#include<stdarg.h>
3
4
voidmain(void){
5
intwilly=harry(2,1,2,3,-2,-3);
6
printf("%i",willy);
7
}
8
9
intharry(intzahl,...){
10
intergebnis=0;
11
va_listarg_ptr;
12
va_start(arg_ptr,zahl);
13
ergebnis+=va_arg(arg_ptr,int);
14
ergebnis+=va_arg(arg_ptr,int);
15
ergebnis+=va_arg(arg_ptr,int);
16
va_end(arg_ptr);
17
return(ergebnis);
18
}
Addieren sich die Argumente einzeln, sprich: (2+2+2+2,1+1+1+1,......) ?
somit wäre das Ergebnis: (8,4,8,12,-8,-12)
oder addieren sich die Argumente im gesamten, sprich: (2+1+2+3-2-3)*3 ?
somit wäre das Ergebnis: (9)
Leider kann ich den Code nicht in einfach testen , da es einige Fehler
zu geben scheint!
Hey ich bin es nochmal.
Ich bereite mich gerade auf eine Informatikklausur (C) vor und habe ein
Problem bei folgender Aufgabe:
Wie ist der Aufruf in Zeile 4 korrekt zu ergänzen, damit anschließend
auf den ersten variablen Parameter der Funktion tueIrgendwas zugegriffen
werden kann?
1: int tueIrgendwas( int iWert, float fWert, ...)
2: {
3: va_list pArg;
4: va_start(
Meine Lösung: pArg,iWert);
Ist diese korrekt?
MfG Dennis
Dennis schrieb:> Hey ich bin es nochmal.> Ich bereite mich gerade auf eine Informatikklausur (C) vor und habe ein> Problem bei folgender Aufgabe:>>>> Wie ist der Aufruf in Zeile 4 korrekt zu ergänzen, damit anschließend> auf den ersten variablen Parameter der Funktion tueIrgendwas zugegriffen> werden kann?>> 1: int tueIrgendwas( int iWert, float fWert, ...)> 2: {> 3: va_list pArg;> 4: va_start(>>> Meine Lösung: pArg,iWert);
Nein.
übliche Leseart in unserem Kulturkreis ist von links nach rechts. D.h.
der letzte benannte Parameter in der Argumentliste war fWert. Bei
va_start gibst du den letzten benannten Parameter an.
http://www.cplusplus.com/reference/cstdarg/va_start/
Dennis schrieb:> Leider kann ich den Code nicht in einfach testen , da es einige Fehler> zu geben scheint!
Wie wärs dann damit, damit anzufangen, die Fehler zu beheben?
Der Rückgabetyp von "main" muss "int" sein, nicht void. Vor der "main"
Funktion muss erst die "harry"-Funktion deklariert werden.
Dennis schrieb:> Addieren sich die Argumente einzeln, sprich: (2+2+2+2,1+1+1+1,......) ?> somit wäre das Ergebnis: (8,4,8,12,-8,-12)>> oder addieren sich die Argumente im gesamten, sprich: (2+1+2+3-2-3)*3 ?> somit wäre das Ergebnis: (9)
Weder noch. Schau dir den Code an:
Dennis schrieb:> ergebnis += va_arg(arg_ptr, int);> ergebnis += va_arg(arg_ptr, int);> ergebnis += va_arg(arg_ptr, int);
Wie viele Additionen zählst du hier? Wie viele Zahlen werden hier also
addiert? Und wie kommst du überhaupt auf *3 ?
Überraschenderweise ist die Funktion von va_arg usw. dokumentiert. Wie
wäre es damit das zu lesen und dann zu überlegen was der Code tut?
https://en.wikipedia.org/wiki/Stdarg.hhttp://www.cplusplus.com/reference/cstdarg/
Nach einiger Überlegung ist mir aufgefallen, dass ich das ergebnis = 0
übersehen habe.
somit wäre ja:
harry( 2, 1, 2, 3, -2, -3 ); = 3
dann folgt:
ergebnis += va_arg(arg_ptr, int);
ergebnis += va_arg(arg_ptr, int);
ergebnis += va_arg(arg_ptr, int);
also wäre das Egebnis 9, richtig?
Der code Compiliert nicht weil die funktion harry vor der ersten
Verwendung noch nicht Deklariert wirde.
Das Ergebnis ist 6:
va_start benötigt als Zweites argument das letzte Argument vor der
Parameterliste der Funkion in der es steht, tut damit aber nichts.
va_arg liefert das nächste Argument. Es werden 3 argumente der variablen
argumentliste mit va_arg geholt, addiert und zurückgegeben. Jedes
Argument das keinem Parameter der funktion entspricht ist teil der
Argumentliste, das erste argument von harry ist zahl und gehlrt zum
ersten parameter von harry, "zahl". Der rest ist teil der variablen
argumentliste. Somit werden 1, 2, und 3 addiert, das ergiebt 6
Dennis schrieb:> also wäre das Egebnis 9, richtig?
Nö.
Die "harry" Funktion ist im übrigen ziemlich bescheuert, weil sie eine
feste Anzahl an Argumenten zum Funktionieren braucht (4) aber dennoch
eine variadische Parameterliste hat, und außerdem das erste Argument und
alle ab dem 5. ignoriert.
Dennis schrieb:> Addieren sich die Argumente einzeln, sprich: (2+2+2+2,1+1+1+1,......) ?> somit wäre das Ergebnis: (8,4,8,12,-8,-12)
Du scheinst da eine sehr seltsame Sichtweise zu haben.
va_arg holt genau 1 Wert von der Argumentliste. Nicht mehr und auch
nicht weniger.
wenn du also einen Aufruf hast
1
...harry(2,1,2,3,-2,-3);
dann geht die erste 2 an die Variable zahl. Denn die ist in der
Argumentliste ja als erstes
1
intharry(intzahl,...)
2
****
die erste Benutzung von va_arg bringt dir die 1
1
...harry(2,1,2,3,-2,-3);
2
***
die nächste Benutzung eine 2
1
...harry(2,1,2,3,-2,-3);
2
***
und die dritte Benutzung die 3
1
...harry(2,1,2,3,-2,-3);
2
***
da keine weiteren va_arg Benutzungen mehr im Code vorkommen, werden die
restlichen Argument nicht weiter benutzt.
Was also ist das Ergebnis von
Vielen Dank für die zahlreichen und schnellen Antworten!
Ich habe jetzt alles verstanden, außer, wieso die 2 nicht erscheint.
ist es wegen " va_start(arg_ptr, zahl); " ?
arg_ptr ruft also die 2 auf und schreibt sie in "zahl", richtig?
Karl H. schrieb:> Nein.> übliche Leseart in unserem Kulturkreis ist von links nach rechts. D.h.> der letzte benannte Parameter in der Argumentliste war fWert. Bei> va_start gibst du den letzten benannten Parameter an.
also va_start(pArg,fWert); ?
Somit würde wäre iWert der erste ausgegebene Wert richtig?
Dennis schrieb:> Vielen Dank für die zahlreichen und schnellen Antworten!>> Ich habe jetzt alles verstanden, außer, wieso die 2 nicht erscheint.>> ist es wegen " va_start(arg_ptr, zahl); " ?> arg_ptr ruft also die 2 auf und schreibt sie in "zahl", richtig?
Nein.
arg_ptr ruft überhaupt nichts auf.
arg_ptr richtet die arg_list so ein, dass die erste Benutzung von va_arg
das nächste Argument von der Argumentliste holt, das nach dem benannten
Parameter 'zahl' auftaucht.
Die erste 2 wird ganz normal an den ersten benannten Parameter gebunden
Dennis schrieb:> und wie greife ich dann auf den ersten Wert zu, bzw was ist denn dann zu> ergänzen, wenn beides unter den Tisch fällt?
Ähm. Über den Variablennamen des Parameters?
1
inttueIrgendwas(intiWert,floatfWert,...)
2
{
3
intirgendwas=iWert+fWert;
4
5
....
mit denen gibt es ja kein Problem. Die haben ja Variablennamen. Nur
alles was danach kommt, dafür hast du keinen Namen mit dem du es
ansprechen könntest.
Rück mal ein wenig zur Seite. Du sitzt gerade mächtig auf der Leitung.
Das ist viel einfacher als du jetzt denkst.
Ahhh, jetzt habe ich das verstanden =)
Vielen Dank Karl Heinz, diese Erklärung hat mir sehr geholfen.
Die zweite Aufgabe verstehe ich allerdings immer noch nicht... :(
Dennis schrieb:> Ahhh, jetzt habe ich das verstanden =)> Vielen Dank Karl Heinz, diese Erklärung hat mir sehr geholfen.>> Die zweite Aufgabe verstehe ich allerdings immer noch nicht... :(
was verstehst du daran nicht.
Beim Aufruf von
1
inttueIrgendwas(intiWert,floatfWert,...)
welches ist denn der erste 'variable Parameter'?
Na der der nach fWert kommt. Denn die ersten beiden sind ja fix. Die
ersten beiden müssen sein, sind also nicht variabel in dem Sinne dass
sie da sein können oder auch nicht.
Mit dem Protoypen klopft dir ein Compiler auf die Finger wenn du
1
tueIrgendwas(5);
machen willst. Denn die Funtkion fordert mindestens 2 Argumente. 2
Argumente sind fix gefordert.
1
tueIrgendwas(5,8);
wäre also ok.
Aber auch
1
tueIrgendwas(5,8,3);
ist ok. die 3 ist halt der erste variable Paramater. er kann da sein,
muss aber nicht.
Wenn also standardmässig sowieso erst mal die Bindung an die benannten
fixen Parameter erfolgt
1
tueIrgendwas( 5, 8, 3 );
2
| |
3
| |
4
v v
5
int tueIrgendwas( int iWert, float fWert, ...)
welche ist dann der letzte benannte Parameter ehe dann der variable Teil
der Argumentliste anfängt?
Genau - fWert.
setzt du die va_list so mit einem va_start auf fWert auf, dann liefert
der erste va_arg dann eben die 3
Ich sitze vermutlich schon viel zu lange vor dem Bildschirm und sollte
eine Pause machen...
wenn ich also also
va_start(pArg,fWert);
aufrufe, dann würde in deinem Beispiel mit einem Aufruf von va_arg die 3
ausgegeben werden, weil diese der erste Variable Wert ist.
Dennis schrieb:> Ich sitze vermutlich schon viel zu lange vor dem Bildschirm und sollte> eine Pause machen...>> wenn ich also also> va_start(pArg,fWert);> aufrufe, dann würde in deinem Beispiel mit einem Aufruf von va_arg die 3> ausgegeben werden, weil diese der erste Variable Wert ist.
An dieser Stelle sind wir soweit, dass man mit Fug und Recht behaupten
kann:
Du hast einen Compiler vor dir. Probier es aus.
Wird die 8 auch in ein float gewandelt
Karl H. schrieb:> Du hast einen Compiler vor dir. Probier es aus.
Da muss man aber aufpassen.
Nicht alles was dein Compiler macht, macht auch ein anderer Compiler.
In C gibt es genug Freiheiten und UB (undefined behaviour)