Compilerfeler, impliziete Konversion und Wirkung undefiniert
-
Konfusius schrieb:
wenn du so eine aufgabe gestellt bekommst, dann müßten deine unterlagen doch auch eine definition dieser begriffe enthalten
.
[...]
hausaufgaben werden hier im forum nicht so gerne gemacht
Ich habe die Aufgabe nicht direkt gestellt bekommen, sondern sie ist in einer Klausur von '98, in meinen Unterlagen steht dazu nichts, und so eine Art Aufgabe kam auch nie wieder vor. Trotzdem will ich die mal gelöst haben.
int x1 [] = {11,12,13}; int x2 [] = {40,20,60}; int x3 [] = {99,77,55}; int * a[]={x3,x2,x1}; int ** p, *p,c; int main(void){ /*1*/ pp=a; /*2*/ pp=a-1; /*3*/ p=*p; /*4*/ p=*(a+1); /*5*/ p=*a+1; /*6*/ p=*(a++); /*7*/ pp=a,p=*(--p); /*8*/ pp=a-1,p=*(++p); /*9*/ pp=a,p=*(p++)-1; /*10*/ c=**a; /*11*/ c=*a; /*12*/ c=a; /*13*/ c=a[2][3]; /*14*/ c=a[3][3]; /*15*/ c=a[3,3]; return 0; }
Ich hab mir mal dran versucht:
1. nichts
2. Com
3. Kon
4. Kon
5. Kon
6. Kon
7. nichts
8. Com
9. Kon, undef
10. Com
11. Kon
12. Com
13. undef
14. undef
15. ComCom = Compilerfehler
Kon = implizite Konversion
undef = Wirkung undefiniert.Eher
oder
?
Ich hab sie jetzt mal ohne Compiler gemacht.
-
cmg schrieb:
int ** p, *p,c;
Das ist schon der erste Compilerfehler - du deklarierst zwei Variablen mit dem selben Namen.
Ich nehme mal an, das erst dort sollte pp heißen und mache weiter:
Schau dir an, was (vor allem wie) implizit umgewandelt werden kann - wenn die Umwandlung möglich ist, erhältst du entweder eine Konvertierung oder undefined behaviour (bei Bereichsüberschreitungen oder nichtinitialisierten Pointern). wenn nicht, ist es ein Compilerfehler.
-
na ok, dann hier meine lösung (wie immer ohne gewähr):
int x1 [] = {11,12,13}; int x2 [] = {40,20,60}; int x3 [] = {99,77,55}; int * a[]={x3,x2,x1}; int ** p, *p,c; // ich unterstelle mal, **p soll eigentlich **pp heißen, sonst com, weil p zweimal deklariert /*1*/ pp=a; // ok /*2*/ pp=a-1; // ok /*3*/ p=*p; // com, zuweisung von int nach int* /*4*/ p=*(a+1); // ok, ist dasselbe wie p=a[1] /*5*/ p=*a+1; // ok, p ist jetzt &x3[1] /*6*/ p=*(a++); // ok, p ist jetzt &x3[0] /*7*/ pp=a,p=*(--p); // com, zuweisung von int nach int* in p=*(--p) // oder undef, da p==*(--p)==*(p-1)==*(a-1)==a[-1] // der komma-operator bindet schwächer als die zuweisung // zusätzlich undef, weil unklar, ob -- vor auswertung von p oder vor auswertung des ganzen ausdrucks erfolgt // kann je nachdem p[0]=p[0] oder p[-1]=p[0] sein /*8*/ pp=a-1,p=*(++p); // com/undef, wie 7 /*9*/ pp=a,p=*(p++)-1; // com/undef, wie 7 /*10*/ c=**a; // ok /*11*/ c=*a; // com, zuweisung von int* nach int /*12*/ c=a; // com, zuweisung von int** nach int /*13*/ c=a[2][3]; // undef, da index nur von 0 bis 2 /*14*/ c=a[3][3]; // undef, wie 13 /*15*/ c=a[3,3]; // com, zuweisung von int* nach int (kein syntaxfehler wegen komma-operator!) // darüber hinaus undef wie 13
ob die zuweisung von int nach int* bzw int* nach int** einen typenfehler herforruft hängt vom alter des compilers ab. neuere c-standards melden einen fehler, ältere erlauben zumindest int* nach int**.
-
Bei 2 würde ich übrigens auch eher auf undef setzen - du willst p auf &(a[-1]) setzen und das liegt außerhalb des erlaubten Index.
-
Nee, 2 ist schon ok. Ist ja letztendlich nur Zeigerarithmetik. Wenn überhaupt, dann ist es Kon, so wie bei 1. undef würde es erst werden, wenn du pp dereferenzierst.
-
groovemaster schrieb:
Nee, 2 ist schon ok.
Nein. Lies nach in C99, Paragraph 6.5.6, Absatz 8:
[...]If both the pointer operand and the result point to elements of the same array object, or one past the past element of the array object, the evaluatoin shall not produce an overflow; otherwise, the behavior is undefined.[...]
-
in endeffekt hängen die antworten sehr stark davon ab, welchen standard man zugrundelegt. im "normalen" c würde (2) keinen compilationzeit- oder laufzeitfehler produzieren. mit c99 kenn ich mich nicht aus.
-
Es geht um ANSI C.
Stimmen deine Ergebnise mit dem Standard überein?
Eine zusätzlich frage habe ich noch:Ist a ein Feld von Zeigern oder ist a ein Zeiger auf ein Feld?
Meiner Meinung nach beides, ist das korrekt?Edit: Ach ja, ist es richtig, dass bei *2* eine implizite Konversion der "1" zu Pointer stattfindet?
-
SG1 schrieb:
Nein. Lies nach in C99, Paragraph 6.5.6, Absatz 8:
[...]If both the pointer operand and the result point to elements of the same array object, or one past the past element of the array object, the evaluatoin shall not produce an overflow; otherwise, the behavior is undefined.[...]
Naja, hast Recht, Overflow ist undef. Auch wenn's im speziellen Fall praktisch nicht auftritt.
cmg schrieb:
Ist a ein Feld von Zeigern oder ist a ein Zeiger auf ein Feld?
a ist ein Array (Feld) von Zeigern.
cmg schrieb:
Edit: Ach ja, ist es richtig, dass bei *2* eine implizite Konversion der "1" zu Pointer stattfindet?
Nein. Die implizite Umwandlung wird bei a durchgeführt, von Array zu Zeiger.
-
cmg schrieb:
Es geht um ANSI C.
der ansi-c-standard wurde immer wieder überarbeitet und weiterentwickelt. deshalb gibt es davon mehrere
ich hab noch auf c89 gelernt (genaugenommen noch khernigan&ritchie). der neueste ist c99.
Stimmen deine Ergebnise mit dem Standard überein?
um ehrlich zu sein: keine ahnung. was in c mit welchem standard übereinstimmt darüber hat kaum jemand wirklich den überblick. deinen lehrer/professor mit an sicherheit grenzender warscheinlichkeit eingeschlossen.
-
groovemaster schrieb:
cmg schrieb:
Ist a ein Feld von Zeigern oder ist a ein Zeiger auf ein Feld?
a ist ein Array (Feld) von Zeigern.
int a[]={x3,x2,x1} wäre doch ein Array von Zeigern, oder nicht?
Dann müsste int *a[]={x3,x2,x1} doch ein Zeiger auf ein Array sein.groovemaster schrieb:
cmg schrieb:
Edit: Ach ja, ist es richtig, dass bei *2* eine implizite Konversion der "1" zu Pointer stattfindet?
Nein. Die implizite Umwandlung wird bei a durchgeführt, von Array zu Zeiger.
PP und a sind doch vom selben Typ, wieso muss da eine Konversion sattfinden?
Sind doch beides quasi Zeiger auf ein Feld.
-
cmg schrieb:
int a[]={x3,x2,x1} wäre doch ein Array von Zeigern, oder nicht?
Nein, ein Array von int.
Dann müsste int *a[]={x3,x2,x1} doch ein Zeiger auf ein Array sein.
Nein, ein Array von Zeigern auf int. Ein Zeiger auf ein Array wird so deklariert:
int (*a)[10];
PP und a sind doch vom selben Typ, wieso muss da eine Konversion sattfinden?
Sind doch beides quasi Zeiger auf ein Feld.quasi
PP ist ein Zeiger auf einen Zeiger auf int, und a ist ein Array von Zeigern auf int. Das ist nicht das gleiche, a wird implizit in einen Zeigertyp umgewandelt. Das passiert bei Arrays fast immer, ausgenommen sind z.B. sizeof-Ausdruecke und vielleicht noch ein, zwei weitere Sachen.
-
Ach sooo, so langsam kommts.
Nochmal eben testen ob ichs wirklich richtig verstanden hab.int x1 [] = {11,12,13}; int x2 [] = {40,20,60}; int x3 [] = {99,77,55}; int * a[]={x3,x2,x1}; int ** pp, *p,c; int main(void){ /*1*/ pp=a; /*2*/ pp=a-1; /*3*/ p=*p; /*4*/ p=*(a+1); /*5*/ p=*a+1; /*6*/ p=*(a++); /*7*/ pp=a,p=*(--pp); /*8*/ pp=a-1,p=*(++pp); /*9*/ pp=a,p=*(pp++)-1; /*10*/ c=**a; /*11*/ c=*a; /*12*/ c=a; /*13*/ c=a[2][3]; /*14*/ c=a[3][3]; /*15*/ c=a[3,3]; return 0; }
Dann wären doch
1,2 implizite Konversionen
genau so wie: 7,8,9
oder?
-
Korrekt, zumindest wenn du bei 7,8,9 den Vorkommateil meinst.
-
danke, dann kann ja morgen nichts mehr schief gehen