{"id":16,"date":"2018-04-23T14:41:57","date_gmt":"2018-04-23T12:41:57","guid":{"rendered":"https:\/\/blogs.urz.uni-halle.de\/cuebung\/?p=16"},"modified":"2018-04-24T10:03:09","modified_gmt":"2018-04-24T08:03:09","slug":"verhalten-von-prinft-in-kombination-mit-incrementi-i-in-c","status":"publish","type":"post","link":"https:\/\/blogs.urz.uni-halle.de\/cuebung\/2018\/04\/verhalten-von-prinft-in-kombination-mit-incrementi-i-in-c\/","title":{"rendered":"Verhalten von prinft in Kombination mit increment(i++\/++i) in C"},"content":{"rendered":"<p>Wie ihr in der \u00dcbung bereits bemerkt habt, hat printf ein seltsames Verhalten, wenn man in den Parametern mehr als ein increment nutzt.<br \/>\nHier nochmal das Beispiel aus der \u00dcbung:<\/p>\n<pre>#include &lt;stdio.h&gt;\r\n<br>void main(){<br>\tint i=0;<br>\tprintf(\"%i %i %i\\n\", i++, i++, i++);<br>\tint i=0;<br>\tprintf(\"%i %i %i\", ++i, ++i, ++i);\r\n<br>}\r\n<\/pre>\n<p>Man w\u00fcrde nun erwarten, dass die Ausgabe wie folgt lautet:<\/p>\n<pre>0 1 2<br>1 2 3<\/pre>\n<p>Die Ausgabe dieses Programms war in der \u00dcbung:<\/p>\n<pre>2 1 0<br>3 3 3<\/pre>\n<p>Man kann sich ruhig einige Sekunden nehmen, dies zu betrachten.<br \/>\ni selbst ist im Grunde nur eine Adresse, an der etwas abgelegt werden kann &#8211; der Wert von i.<br \/>\nNach i++ h\u00e4lt i nach wie vor dieselbe Adresse, aber der Wert von i wurde um 1 erh\u00f6ht.<\/p>\n<p><strong>Der printf Befehl wertet solche increment Operationen aus, bevor die Ausgabe mit den entsprechenden Werten der Variablen konstruiert wird.<\/strong><br \/>\nDies zeigt sich an dem folgenden Beispiel.<\/p>\n<p>Der Code von oben wurde leicht modifiziert:<\/p>\n<pre>#include &lt;stdio.h&gt;\r\n<br>void main(){<br>\tint i=0;<br>\tprintf(\"%i %i %i\\n\", i++, i, i++);<br>\tint i=0;<br>\tprintf(\"%i %i %i\", ++i, i, ++i);\r\n<br>}\r\n<\/pre>\n<p>Die Ausgabe ist nun:<\/p>\n<pre>1 2 0<br>2 2 2<\/pre>\n<h1><strong>Warum dieses seltsame, unerwartete Verhalten?<\/strong><\/h1>\n<p><span style=\"color: #ff0000\"><strong>Kurz: In C ist das Verhalten f\u00fcr 2 increment Operationen in einer Anweisung nicht definiert.<\/strong> <\/span><\/p>\n<p>Lang: Der <a href=\"https:\/\/de.wikipedia.org\/wiki\/Compiler\">Compiler<\/a> optimiert das C-Porgramm f\u00fcr die jeweilige <a href=\"https:\/\/de.wikipedia.org\/wiki\/Plattform_(Computer)\">Plattform<\/a>, auf der er l\u00e4uft.<\/p>\n<p>Da f\u00fcr die Auswertung einer Anweisung laut C-Handbuch keine feste Reihenfolge festgelegt ist, liegt es beim Compiler, wie die obige printf Anweisung ausgewertet werden soll.<\/p>\n<blockquote><p>If A is not sequenced before or after B then A and B are unsequenced Evaluations A and B are indeterminately sequenced when A is sequenced either before or after B, but it is unspecified which. 13) The presence of a sequence point between the evaluation of expressions A and B implies that every value computation and side effect associated with A is sequenced before every value computation and side effect associated with B. <em><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg14\/www\/docs\/n1570.pdf#%5B%7B%22num%22%3A66%2C%22gen%22%3A0%7D%2C%7B%22name%22%3A%22XYZ%22%7D%2C-27%2C816%2Cnull%5D\">ISO\/IEC 9899:201x 5.1.2.3 \u00a73<\/a><br \/>\n<\/em><\/p><\/blockquote>\n<p>Hier scheinbar &#8222;von rechts nach links&#8220;.<\/p>\n<p><span style=\"color: #ff0000\"><strong>Dieses Verhalten ist aber keinenfalls als Regel anzusehen! <\/strong><\/span><br \/>\n<span style=\"color: #ff0000\"><strong>Das Verhalten kann sich stark unterscheiden zwischen verschiedenen Plattformen und kann sogar Compiler abh\u00e4ngig sein!<\/strong><\/span><\/p>\n<h3><span style=\"color: #ff0000\"><strong>Mehr als eine increment Operation in einer Anweisung hat kein eindeutig festgelegetes Verhalten zufolge!<\/strong><\/span><\/h3>\n<h1>Wie geht das richtig?<\/h1>\n<p>Will man ein Programm mit der Intention vom ersten Programm haben, kann man das so l\u00f6sen:<\/p>\n<pre>#include &lt;stdio.h&gt;<br>void main(){<br>\tprintf(\"%i %i %i\\n\", i++, i+1, i+2);<br>\tint i=0;<br>\ti=i+2;<br>\tprintf(\"%i %i %i\", ++i, i+1, i+2);<br>\ti=i+2;<br>}\r\n<\/pre>\n<p>Nach beiden printf Anweisungen stimmt der Zustand der Variablen noch nicht mit dem oben im ersten Beispiel \u00fcberein.<br \/>\nDeshalb muss noch eine Zeile i=i+2 hinzugef\u00fcgt werden. Nun erreichen wir nach diesen 2 Zeilen den gleichen Zustand bez\u00fcglich der Variablen wie oben, nur hier ist die Ausgabe von printf \u00fcber alle Plattformen und Compiler eindeutig definiert.<\/p>\n<p>Die Ausgabe ist:<\/p>\n<pre>0 1 2<br>1 2 3<\/pre>\n<p>Es gibt Sprachen in denen es eindeutig ist, in welcher Reihenfolge mehrere dieser increments abgearbeitet werden, aber es ist allgemein guter Stil, es nicht darauf ankommen zu lassen.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wie ihr in der \u00dcbung bereits bemerkt habt, hat printf ein seltsames Verhalten, wenn man in den Parametern mehr als ein increment nutzt. Hier nochmal das Beispiel aus der \u00dcbung: #include &lt;stdio.h&gt; void main(){ int i=0; printf(&#8222;%i %i %i\\n&#8220;, i++, i++, i++); int i=0; printf(&#8222;%i %i %i&#8220;, ++i, ++i, ++i); } Man w\u00fcrde nun erwarten, [&hellip;]<\/p>\n","protected":false},"author":3370,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.urz.uni-halle.de\/cuebung\/wp-json\/wp\/v2\/posts\/16"}],"collection":[{"href":"https:\/\/blogs.urz.uni-halle.de\/cuebung\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.urz.uni-halle.de\/cuebung\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.urz.uni-halle.de\/cuebung\/wp-json\/wp\/v2\/users\/3370"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.urz.uni-halle.de\/cuebung\/wp-json\/wp\/v2\/comments?post=16"}],"version-history":[{"count":10,"href":"https:\/\/blogs.urz.uni-halle.de\/cuebung\/wp-json\/wp\/v2\/posts\/16\/revisions"}],"predecessor-version":[{"id":40,"href":"https:\/\/blogs.urz.uni-halle.de\/cuebung\/wp-json\/wp\/v2\/posts\/16\/revisions\/40"}],"wp:attachment":[{"href":"https:\/\/blogs.urz.uni-halle.de\/cuebung\/wp-json\/wp\/v2\/media?parent=16"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.urz.uni-halle.de\/cuebung\/wp-json\/wp\/v2\/categories?post=16"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.urz.uni-halle.de\/cuebung\/wp-json\/wp\/v2\/tags?post=16"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}