<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Zuweisungen]]></title><description><![CDATA[<p>Hi, ich versuche zu verstehen wie die folgende Zuweisung funktioniert</p>
<pre><code class="language-cpp">int erg = ((i = i + 1) * (i = i + 1) * (i = i + 1));
</code></pre>
<p>Dazu habe ich mir den folgenden Code geschrieben:</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;

int main()
{
	int i = 2;

        //Variante 1
	int erg = ((i = i + 1) * (i = i + 1) * (i = i + 1)); //Was wird hier genau gemacht?
	cout &lt;&lt; erg &lt;&lt; endl;

	i = 2;

        //Variante 2
	i = i + 1;
	i = i + 1;
	i = i + 1;
	cout &lt;&lt; (i * i * i);

	return 0;
}
</code></pre>
<p>Ich hatte zunächst angenommen dass die Zuweisung die in Variante 1 steht im Prinzip das gleiche ist wie Variante 2 nur anders geschrieben. Doch da hab ich<br />
mich geirrt, denn das Ergebnis der Variante 1 lautet 80, während das Ergebnis der Variante 2 aber 125 lautet.</p>
<p>Kann mir jemand erklären wie Variate 1 funktioniert?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/308833/zuweisungen</link><generator>RSS for Node</generator><lastBuildDate>Wed, 05 Aug 2026 17:13:19 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/308833.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 07 Oct 2012 10:41:45 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 10:41:45 GMT]]></title><description><![CDATA[<p>Hi, ich versuche zu verstehen wie die folgende Zuweisung funktioniert</p>
<pre><code class="language-cpp">int erg = ((i = i + 1) * (i = i + 1) * (i = i + 1));
</code></pre>
<p>Dazu habe ich mir den folgenden Code geschrieben:</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;

int main()
{
	int i = 2;

        //Variante 1
	int erg = ((i = i + 1) * (i = i + 1) * (i = i + 1)); //Was wird hier genau gemacht?
	cout &lt;&lt; erg &lt;&lt; endl;

	i = 2;

        //Variante 2
	i = i + 1;
	i = i + 1;
	i = i + 1;
	cout &lt;&lt; (i * i * i);

	return 0;
}
</code></pre>
<p>Ich hatte zunächst angenommen dass die Zuweisung die in Variante 1 steht im Prinzip das gleiche ist wie Variante 2 nur anders geschrieben. Doch da hab ich<br />
mich geirrt, denn das Ergebnis der Variante 1 lautet 80, während das Ergebnis der Variante 2 aber 125 lautet.</p>
<p>Kann mir jemand erklären wie Variate 1 funktioniert?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2257807</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257807</guid><dc:creator><![CDATA[blupblup]]></dc:creator><pubDate>Sun, 07 Oct 2012 10:41:45 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 10:47:38 GMT]]></title><description><![CDATA[<p>halte dich damit nicht auf, das Ergebnis ist undefiniert.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2257809</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257809</guid><dc:creator><![CDATA[otze]]></dc:creator><pubDate>Sun, 07 Oct 2012 10:47:38 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 10:53:45 GMT]]></title><description><![CDATA[<p>Woher hast du den Quatsch denn? ^^</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2257812</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257812</guid><dc:creator><![CDATA[_matze]]></dc:creator><pubDate>Sun, 07 Oct 2012 10:53:45 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 10:57:23 GMT]]></title><description><![CDATA[<p>Mit undefiniert meinst du, dass es einfach falsch berechnet wird,<br />
weils ein unzulässiger Ausdruck ist?</p>
<p>Und was ist damit?<br />
Ist das Ergebnis auch undefiniert?<br />
Ich habe dieses Beispiel nämlich im Internet gefunden,<br />
aber ich kann hier einfach nicht nachvollziehen, wieso<br />
das Ergebnis dieser Berechnung 36 ist.</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;

#define QUAD(x) ((x) * (x))

int main()
{
	int x = 4;
	int erg = QUAD(++x);
	cout &lt;&lt; erg; // liefert 36

	return 0;
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2257814</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257814</guid><dc:creator><![CDATA[blupblup]]></dc:creator><pubDate>Sun, 07 Oct 2012 10:57:23 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 11:04:48 GMT]]></title><description><![CDATA[<p>blupblup schrieb:</p>
<blockquote>
<p>Und was ist damit?<br />
Ist das Ergebnis auch undefiniert?</p>
</blockquote>
<p>Ja, wenn QUAD kein Makro, sondern eine Funktion wäre (so wie man es richtig machen würde), dann wäre es nicht undefiniert...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2257816</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257816</guid><dc:creator><![CDATA[dot]]></dc:creator><pubDate>Sun, 07 Oct 2012 11:04:48 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 11:06:17 GMT]]></title><description><![CDATA[<p>Auf der Seite wo ich das nachfolgende Beispiele habe,<br />
soll ein Funktionsaufruf mit einem Makroaufruf verglichen werden.</p>
<p>Der Funktionsaufruf und der Makroaufruf scheinen dieselbe Berechnung<br />
zu machen, wenn man das Programm allerdings startet zeigt sich,<br />
dass dem nicht so ist. Leider steht zu dem Beispiel nichts weiter,<br />
so dass ich nicht verstehe woran das liegt.</p>
<p>Nun versteh ich die Aussage des Beispiels auch nicht. Soll es zeigen,<br />
dass das Makro so nicht aufgerunfen werden kann wie im Beispiel gezeigt?<br />
Berechnet das Makro einen falschen Wert? Oder ist der Wert richtig<br />
und man muss sich die Berechnung irgendwie anders vorstellen?</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;

#define QUAD(x) ((x) * (x))

int quadrat(int);

int main()
{
	int x = 4;
	int erg = QUAD(++x); //erg = 36
	cout &lt;&lt; erg &lt;&lt; endl; 

	int y = 4;
	int erg2 = quadrat(++y); //erg2 = 25
	cout &lt;&lt; erg2;

	return 0;
}

int quadrat(int x)
{
	return x * x;
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2257817</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257817</guid><dc:creator><![CDATA[blupblup]]></dc:creator><pubDate>Sun, 07 Oct 2012 11:06:17 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 11:11:03 GMT]]></title><description><![CDATA[<p><strong>Dir fehlt Grundwissen, hol dir ein gutes Buch.</strong></p>
<p>Thread gibts in der FAQ.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2257820</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257820</guid><dc:creator><![CDATA[Sone]]></dc:creator><pubDate>Sun, 07 Oct 2012 11:11:03 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 11:13:24 GMT]]></title><description><![CDATA[<p>Das Beispiel soll einfach zeigen, dass ein Makro nicht mit einem Vergleichsaufruf gleichzusetzen ist, leider benutzt es vielleicht fragwürdige Beispiele oder erläutert diese nicht genau.</p>
<p>Wenn du folgenden Source hast:</p>
<pre><code class="language-cpp">double square( double in ) { return in*in; }
#define SQUARE(x) ((x)*(x))
a = SQUARE(++test);
b = square(++test);
</code></pre>
<p>Dann sieht der C++-Compiler, nachdem der Präprozessor mit dem Makro fertig ist:</p>
<pre><code class="language-cpp">a = ((++test)*(++test));  // Ups!
b = square(++test);       // Ok!
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2257821</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257821</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Sun, 07 Oct 2012 11:13:24 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 11:25:55 GMT]]></title><description><![CDATA[<p>blupblup schrieb:</p>
<blockquote>
<p>Auf der Seite wo ich das nachfolgende Beispiele habe,<br />
soll ein Funktionsaufruf mit einem Makroaufruf verglichen werden.</p>
<p>Der Funktionsaufruf und der Makroaufruf scheinen dieselbe Berechnung<br />
zu machen, wenn man das Programm allerdings startet zeigt sich,<br />
dass dem nicht so ist. Leider steht zu dem Beispiel nichts weiter,<br />
so dass ich nicht verstehe woran das liegt.</p>
<p>Nun versteh ich die Aussage des Beispiels auch nicht. Soll es zeigen,<br />
dass das Makro so nicht aufgerunfen werden kann wie im Beispiel gezeigt?<br />
Berechnet das Makro einen falschen Wert? Oder ist der Wert richtig<br />
und man muss sich die Berechnung irgendwie anders vorstellen?</p>
</blockquote>
<p>Die Aussage des Beispiels soll vermutlich sein: Makros sind böse und sollten nicht verwendet werden (zumindest nicht für sowas). <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>Ist der Wert denn deiner Meinung nach richtig? Was findest du, sollte bei QUAD(++x) rauskommen?</p>
<p>Anyway, hier die Erklärung:</p>
<pre><code class="language-cpp">int erg = QUAD(++x);
</code></pre>
<p>expandiert zu</p>
<pre><code class="language-cpp">int erg = ((++x) * (++x));
</code></pre>
<p>Es ist allerdings undefiniert, wann genau während der Auswertung dieses Ausdruckes der Inkrement passiert. Das einzige, was garantiert ist, ist, dass <em>nach</em> der Auswertung des <em>ganzen</em> Ausdruckes x um 2 inkrementiert wurde. Das Ergebnis kann daher also 16, 20, 24, 25, 30 oder 36 sein.<br />
Bei der Variante mit der Funktion gibt es das Problem nicht und das Ergebnis ist daher garantiert 25.<br />
Wenn du allerdings sowas hättest:</p>
<pre><code class="language-cpp">void blub(int x, int y)
{
  return x * y;
}

int x = 4;
int erg = blub(++x, ++x);
</code></pre>
<p>wär das Ergebnis wieder undefiniert...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2257823</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257823</guid><dc:creator><![CDATA[dot]]></dc:creator><pubDate>Sun, 07 Oct 2012 11:25:55 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 11:21:26 GMT]]></title><description><![CDATA[<p>blupblup schrieb:</p>
<blockquote>
<pre><code class="language-cpp">#define QUAD(x) ((x) * (x))
int main()
{
	int x = 4;
	int erg = QUAD(++x);
}
</code></pre>
</blockquote>
<p>Schauen wir mal. Ein Makro ersetzt ja einfach nur etwas. Also steht da:</p>
<pre><code class="language-cpp">int x = 4;
	int erg = ((++x) * (++x));
</code></pre>
<p>C++ garantiert nicht, wann ein Seiteneffekt (Änderung des Speicherbereichs) eintritt. D.h. der Operator <code>++</code> gibt dir schön den um 1 erhöhten Wert zurück. Aber niemand weiß, ob der neue Wert schon auf die Variable geschrieben wird. Also kann vieles passieren:</p>
<pre><code class="language-cpp">int x = 4;
	int erg = ((5) * (5));
</code></pre>
<p>oder</p>
<pre><code class="language-cpp">int x = 4;
	int erg = ((6) * (6));
</code></pre>
<p>oder</p>
<pre><code class="language-cpp">int x = 4;
	int erg = ((5) * (6));
</code></pre>
<p>oder...</p>
<p>C++ garantiert dir aber, dass ein Seiteneffekt spätestens nach einem sequence-point (google wikipedia) eingetreten ist. D.h. erst nach der Anweisung <code>int erg = ((++x) * (++x));</code> kannst du sicher sein, dass x=6 ist.</p>
<pre><code class="language-cpp">int quadrat(int x)
{
    return x * x;
}

int main()
{
    int y = 4;
    int erg2 = quadrat(++y); //erg2 = 25
}
</code></pre>
<p>Hier ist es GANZ anders. Ein Funktionsaufruf stellt bereits ein sequence-point dar. D.h es ist sicher, dass der Parameter x den Wert 5 hat. Und 5*5 ist nunmal 25. :p</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2257825</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257825</guid><dc:creator><![CDATA[out]]></dc:creator><pubDate>Sun, 07 Oct 2012 11:21:26 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 11:47:34 GMT]]></title><description><![CDATA[<p>Ich habe mal eine kleine Übersicht zum ersten Problem erstellt:</p>
<pre><code class="language-cpp">int erg = ((i = i + 1) * (i = i + 1) * (i = i + 1));
          ^^^^^^1^^^^^   ^^^^^2^^^^^   ^^^^^3^^^^^

//                                              op       side effect
int L0 = i;                // load(1)           (a)      
int L1 = L0 + 1;           // add(1)            (b)                     (a)&lt;(b) 1.9/15s.2
i = L1;                    // store(1)          (c)      *              (b)&lt;(c) 5.17/1s.4
int L2 = L1;               // stored value(1)   (d)                     (c)&lt;(d) 5.17/1s.4

int L3 = i;                // load(2)           (e)
int L4 = L3 + 1;           // add(2)            (f)
i = L4;                    // store(2)          (g)      *
int L5 = L4;               // stored value(2)   (h)

int L6 = i;                // load(3)           (i)
int L7 = L6 + 1;           // add(3)            (j)
i = L7;                    // store(3)          (k)      *
int L8 = L7;               // stored value(3)   (l)

int L9 = L2 * L5;          // mul(1,2)          (m)                     (d)&lt;(m)  (h)&lt;(m)
int L10 = L9 * L8;         // mul(12,3)         (n)                     (l)&lt;(n)  (m)&lt;(n)

erg = L7;                  // store             (o)      *              (o)&lt;(n)

// &lt; sequenced before
// &gt; sequenced after
// | indeterminately sequenced 
// ~ unsequenced (1.9/15s1)
// # unsequenced UB (1.9/15s3)

//   a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
//a      &lt;   &lt;   &lt;   ~   ~   #   ~   ~   ~   #   ~   &lt;   &lt;   &lt;
//b   &gt;      &lt;   &lt;   ~   ~   ~   ~   ~   ~   ~   ~   &lt;   &lt;   &lt;
//c   &gt;   &gt;      &lt;   #   ~   #   ~   #   ~   #   ~   &lt;   &lt;   &lt;
//d   &gt;   &gt;   &gt;      ~   ~   ~   ~   ~   ~   ~   ~   &lt;   &lt;   &lt;
//e   ~   ~   #   ~      &lt;   &lt;   &lt;   ~   ~   #   ~   &lt;   &lt;   &lt;
//f   ~   ~   ~   ~   &gt;      &lt;   &lt;   ~   ~   ~   ~   &lt;   &lt;   &lt;
//g   #   ~   #   ~   &gt;   &gt;      &lt;   #   ~   #   ~   &lt;   &lt;   &lt;
//h   ~   ~   ~   ~   &gt;   &gt;   &gt;      ~   ~   ~   ~   &lt;   &lt;   &lt;
//i   ~   ~   #   ~   ~   ~   #   ~      &lt;   &lt;   &lt;   ~   &lt;   &lt;
//j   ~   ~   ~   ~   ~   ~   ~   ~   &gt;      &lt;   &lt;   ~   &lt;   &lt;
//k   #   ~   #   ~   #   ~   #   ~   &gt;   &gt;      &lt;   ~   &lt;   &lt;
//l   ~   ~   ~   ~   ~   ~   ~   ~   &gt;   &gt;   &gt;      ~   &lt;   &lt;
//m   &gt;   &gt;   &gt;   &gt;   &gt;   &gt;   &gt;   &gt;   ~   ~   ~   ~      &lt;   &lt;
//n   &gt;   &gt;   &gt;   &gt;   &gt;   &gt;   &gt;   &gt;   &gt;   &gt;   &gt;   &gt;   &gt;      &lt;
//o   &gt;   &gt;   &gt;   &gt;   &gt;   &gt;   &gt;   &gt;   &gt;   &gt;   &gt;   &gt;   &gt;   &gt;
</code></pre>
<p>Der Begriff <em>sequence point</em> wird ja so nicht mehr verwendet.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2257827</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257827</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Sun, 07 Oct 2012 11:47:34 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 11:46:23 GMT]]></title><description><![CDATA[<p>dot schrieb:</p>
<blockquote>
<pre><code class="language-cpp">int erg = ((++x) * (++x));
</code></pre>
<p>Es ist allerdings undefiniert, wann genau während der Auswertung dieses Ausdruckes der Inkrement passiert. Das einzige, was garantiert ist, ist, dass <em>nach</em> der Auswertung des <em>ganzen</em> Ausdruckes x um 2 inkrementiert wurde. Das Ergebnis kann daher also 16, 20, 24, 25, 30 oder 36 sein.<br />
Bei der Variante mit der Funktion gibt es das Problem nicht und das Ergebnis ist daher garantiert 25.<br />
Wenn du allerdings sowas hättest:</p>
<pre><code class="language-cpp">void blub(int x, int y)
{
  return x * y;
}

int x = 4;
int erg = blub(++x, ++x);
</code></pre>
<p>wär das Ergebnis wieder undefiniert...</p>
</blockquote>
<p>Achso verstehe. Das Beispiel mit der Funktion ist auch interessant, das hätte<br />
ich nicht erwartet.</p>
<p>Also Aufrufe mit ++x sollte man bei Makros immer sein lassen.<br />
Wenn das Makro wie nachfolgend lauten würde könnte es dann sein,<br />
dass der Variablen erg manchmal der Wert 2 und manchmal der Wert 3 zugewiesen wird?<br />
Gäbe es also hier ein ähnliches Problem wie bei dem QUAD(X) Beispiel?</p>
<pre><code class="language-cpp">#define BLA(x) (x)

int main()
{
    int a = 2;
    int erg = BLA(++a);
    return 0;
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2257828</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257828</guid><dc:creator><![CDATA[blupblup]]></dc:creator><pubDate>Sun, 07 Oct 2012 11:46:23 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 11:45:04 GMT]]></title><description><![CDATA[<p>blupblup schrieb:</p>
<blockquote>
<p>Also Aufrufe mit ++x sollte man bei Makros immer sein lassen.</p>
</blockquote>
<p>Nicht unbedingt, allerdings sind Makros sowieso zu vermeiden. Für sowas generell besser (inline) Funktionen verwenden.</p>
<p>blupblup schrieb:</p>
<blockquote>
<p>Wenn das Makro wie nachfolgend lauten würde könnte es dann sein,<br />
dass manchmal der Wert 2 und manchmal der Wert 3 ausgegeben wird?<br />
Gäbe es also hier ein ähnliches Problem wie bei dem QUAD(X) Beispiel?</p>
<pre><code class="language-cpp">#define BLA(x) (x)

int main()
{
    int a = 2;
    int erg = BLA(++a);
    return 0;
}
</code></pre>
</blockquote>
<p>Nope, da kommt ganz sicher immer 3 raus. Das Problem hat nicht mit dem Makro an sich zu tun, sondern damit, dass du mehrere Inkrements im selben Ausdruck stehen hast...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2257829</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257829</guid><dc:creator><![CDATA[dot]]></dc:creator><pubDate>Sun, 07 Oct 2012 11:45:04 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 11:51:33 GMT]]></title><description><![CDATA[<p>Okay verstehe.<br />
Danke für die Hilfe.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2257833</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257833</guid><dc:creator><![CDATA[blupblup]]></dc:creator><pubDate>Sun, 07 Oct 2012 11:51:33 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 12:03:47 GMT]]></title><description><![CDATA[<p>Merk dir einfach die Faustregel: Innerhalb eine Anweisung darf eine Variable max. 1x modifiziert werden. Hälst du dich daran, bist du stets auf der sicheren Seite.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2257834</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257834</guid><dc:creator><![CDATA[out]]></dc:creator><pubDate>Sun, 07 Oct 2012 12:03:47 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 13:15:35 GMT]]></title><description><![CDATA[<p>Genau wie out sagt, denn genau deshalb ist</p>
<pre><code class="language-cpp">a = f(i++,i);
</code></pre>
<p>auch wohl definiert!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2257857</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257857</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Sun, 07 Oct 2012 13:15:35 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 13:26:37 GMT]]></title><description><![CDATA[<p>Decimad schrieb:</p>
<blockquote>
<p>Genau wie out sagt, denn genau deshalb ist</p>
<pre><code class="language-cpp">a = f(i++,i);
</code></pre>
<p>auch wohl definiert!</p>
</blockquote>
<p>Nope, ist es nicht, die Auswertungsreihenfolge der Parameter ist nicht definiert. Es ist lediglich garantiert, dass der eine vor dem anderen ausgewertet wird, aber nicht, welcher zuerst.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2257863</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257863</guid><dc:creator><![CDATA[dot]]></dc:creator><pubDate>Sun, 07 Oct 2012 13:26:37 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 13:25:01 GMT]]></title><description><![CDATA[<p>out schrieb:</p>
<blockquote>
<pre><code class="language-cpp">int x = 4;
	int erg = ((++x) * (++x));
</code></pre>
<p>[...] D.h. erst nach der Anweisung <code>int erg = ((++x) * (++x));</code> kannst du sicher sein, dass x=6 ist.</p>
</blockquote>
<p>nein. Wenn der Compiler gut optimiert, kommt wahrscheinlich x==5 raus - mit UB ist es allerdings sinnlos, auf irgendein konkretes Ergebnis zu wetten.</p>
<p>out schrieb:</p>
<blockquote>
<p>Merk dir einfach die Faustregel: Innerhalb eine Anweisung darf eine Variable max. 1x modifiziert werden. Hälst du dich daran, bist du stets auf der sicheren Seite.</p>
</blockquote>
<p>Das vermeidet eine Stolperfalle, hinreichend für wohldefiniertes Verhalten ist das noch lange nicht.</p>
<p>Decimad schrieb:</p>
<blockquote>
<p>Genau wie out sagt, denn genau deshalb ist</p>
<pre><code class="language-cpp">a = f(i++,i);
</code></pre>
<p>auch wohl definiert!</p>
</blockquote>
<p>Leider hat auch dieser Code undefiniertes Verhalten (ich nehme mal an, dass f eine Funktion oder eine Klasse mit geeignetem Konstruktor sein soll)</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2257866</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257866</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Sun, 07 Oct 2012 13:25:01 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 13:55:31 GMT]]></title><description><![CDATA[<p>camper schrieb:</p>
<blockquote>
<p>out schrieb:</p>
<blockquote>
<p>Merk dir einfach die Faustregel: Innerhalb eine Anweisung darf eine Variable max. 1x modifiziert werden. Hälst du dich daran, bist du stets auf der sicheren Seite.</p>
</blockquote>
<p>Das vermeidet eine Stolperfalle, hinreichend für wohldefiniertes Verhalten ist das noch lange nicht.</p>
</blockquote>
<p>Hast du ein Beispiel parat, in dem eine Variable innerhalb einer Anweisung nur 1x modifiziert wird und es trotzdem zu UB kommt?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2257882</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257882</guid><dc:creator><![CDATA[out]]></dc:creator><pubDate>Sun, 07 Oct 2012 13:55:31 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 13:58:41 GMT]]></title><description><![CDATA[<p>out schrieb:</p>
<blockquote>
<p>camper schrieb:</p>
<blockquote>
<p>out schrieb:</p>
<blockquote>
<p>Merk dir einfach die Faustregel: Innerhalb eine Anweisung darf eine Variable max. 1x modifiziert werden. Hälst du dich daran, bist du stets auf der sicheren Seite.</p>
</blockquote>
<p>Das vermeidet eine Stolperfalle, hinreichend für wohldefiniertes Verhalten ist das noch lange nicht.</p>
</blockquote>
<p>Hast du ein Beispiel parat, in dem eine Variable innerhalb einer Anweisung nur 1x modifiziert wird und es trotzdem zu UB kommt?</p>
</blockquote>
<pre><code class="language-cpp">i = j++;
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2257883</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257883</guid><dc:creator><![CDATA[Sone]]></dc:creator><pubDate>Sun, 07 Oct 2012 13:58:41 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 14:00:09 GMT]]></title><description><![CDATA[<p>out schrieb:</p>
<blockquote>
<p>camper schrieb:</p>
<blockquote>
<p>out schrieb:</p>
<blockquote>
<p>Merk dir einfach die Faustregel: Innerhalb eine Anweisung darf eine Variable max. 1x modifiziert werden. Hälst du dich daran, bist du stets auf der sicheren Seite.</p>
</blockquote>
<p>Das vermeidet eine Stolperfalle, hinreichend für wohldefiniertes Verhalten ist das noch lange nicht.</p>
</blockquote>
<p>Hast du ein Beispiel parat, in dem eine Variable innerhalb einer Anweisung nur 1x modifiziert wird und es trotzdem zu UB kommt?</p>
</blockquote>
<pre><code class="language-cpp">int y = x++ + x;
</code></pre>
<p>Sone schrieb:</p>
<blockquote>
<pre><code class="language-cpp">i = j++;
</code></pre>
</blockquote>
<p>Wo genau versteckt sich das UB?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2257884</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257884</guid><dc:creator><![CDATA[dot]]></dc:creator><pubDate>Sun, 07 Oct 2012 14:00:09 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 14:13:48 GMT]]></title><description><![CDATA[<p>dot schrieb:</p>
<blockquote>
<p>out schrieb:</p>
<blockquote>
<p>camper schrieb:</p>
<blockquote>
<p>out schrieb:</p>
<blockquote>
<p>Merk dir einfach die Faustregel: Innerhalb eine Anweisung darf eine Variable max. 1x modifiziert werden. Hälst du dich daran, bist du stets auf der sicheren Seite.</p>
</blockquote>
<p>Das vermeidet eine Stolperfalle, hinreichend für wohldefiniertes Verhalten ist das noch lange nicht.</p>
</blockquote>
<p>Hast du ein Beispiel parat, in dem eine Variable innerhalb einer Anweisung nur 1x modifiziert wird und es trotzdem zu UB kommt?</p>
</blockquote>
<pre><code class="language-cpp">int y = x++ + x;
</code></pre>
</blockquote>
<p>Stimmt. Dann muss man die Faustregel etwas strengen auslegen: Zwischen zwei sequence-points darf eine modifiziere Variable höchstens 1x auftauchen. Dann ist man wirklich safe, oder?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2257889</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257889</guid><dc:creator><![CDATA[out]]></dc:creator><pubDate>Sun, 07 Oct 2012 14:13:48 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 14:24:21 GMT]]></title><description><![CDATA[<p>Ich glaube, + ist kein Sequence Point, auch wenn der Begriff veraltet ist.</p>
<p>Und schlagt mich, aber: camper, die Tabelle sieht echt super aus, aber was genau drückt eine Zelle aus, wie werden Zeile und Spalte genau miteinander vermengt? Sorry, wenn das da irgendwie draus hervorgeht. Wenn Dir die Frage zu doof ist, vergiss sie.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2257891</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257891</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Sun, 07 Oct 2012 14:24:21 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 14:26:46 GMT]]></title><description><![CDATA[<p>Eisflamme schrieb:</p>
<blockquote>
<p>Ich glaube, + ist kein Sequence Point, auch wenn der Begriff veraltet ist.</p>
</blockquote>
<p>Eben, ist es auch nicht.<br />
Ist der Begriff für C++98/03 auch veraltet? Dachte das gilt nur für de neuen Standard.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2257895</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257895</guid><dc:creator><![CDATA[out]]></dc:creator><pubDate>Sun, 07 Oct 2012 14:26:46 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 14:52:40 GMT]]></title><description><![CDATA[<p>Allgemein:<br />
Im Allgemeinen (sofern nichts anderes gesagt wird) ist die Auswertung von Ausdrücken ungeordnet (unsequenced) im Verhältnis zur Auswertung irgendwelcher anderer Ausdrücke (1.9/15 Satz 1)<br />
Sofern zwei Ausdrücke das gleiche Objekt modifizieren oder einer das Objekt modifiziert und der andere vom gespeicherten Wert des Objektes abhängt, ist das Verhalten undefiniert, wenn die Auswertung der beiden Ausdrücke nicht geordnet (sequenced) ist (1.9/15 Satz 3)</p>
<p>Zum Glück gibt es nicht sehr viele (allgemeine) Regeln, die die Reihenfolge der Auswertung festlegen:</p>
<p>1. die Operanden eines Operators werden ausgewertet, bevor das Ergebnis des Operators berechnet wird (1.9/15 Satz 2), also in</p>
<pre><code class="language-cpp">(1+2)+(3+4)
</code></pre>
<p>werden erst 1+2 und 3+4 ausgewertet, bevor die Gesamtsumme gebildet wird. Das ist im Prinzip intuitiv klar.<br />
Ausnahmen sind bei bestimmten Operatoren (&amp;&amp; || ?: ,) zu beachten.</p>
<p>2. Ausdrücke, die zu verschiedenen Anweisungen gehören, werden in der Reihenfolge ausgewertet, in der die Anweisungen stehen (a.k.a &quot;;&quot; ist ein Sequenzpunkt) 1.9/14.</p>
<p>3. Argumente für Funktionsaufrufe werden ausgewertet, bevor die Funktion aufgerufen wird (die Auswertung der Argumente untereinander ist aber - bis auf eine Ausnahme - unbestimmt) 1.9/15 Satz 4.</p>
<p>4. (Teil-)Ausdrücke (einschließlich anderer Funktionsaufrufe), die zum gleichen <em>vollständigen Ausdruck</em> wie ein Funktionsaufruf gehören, werden in unbestimmter Weise entweder vor oder nach dem Funktionsaufruf ausgeführt (indeterminately sequenced) 1.9/15 Satz 5. (das bedeutet auch, das Funktionsaufrufe nicht überlappen).</p>
<p>(Eine Regel mit kleinerer Nummer hat jeweils Vorrang). Das sind ungefähr die Regeln, die man sich als Anfänger aneignen sollte, um den häufigsten Stolperfallen aus dem Weg zu gehen.</p>
<p>Ein paar Besonderheiten sind bei , &amp;&amp; || ?: zu beachten - das ist bekannt.<br />
Die Zuweisung macht ein paar zusätzliche Garantien:<br />
- der Wert der Zuweisung wird erst bestimmt, nachdem das Objekt modifiziert wurde. Damit werden Mehrfachzuweisungen der Form</p>
<pre><code class="language-cpp">a = b = 0;
</code></pre>
<p>möglich.<br />
- Es ist garantiert, dass der Wert der Zuweisung mit dem in der Zuweisung gespeicherten Wert übereinstimmt im Verhältnis zu einem Funktionsaufruf im gleichen vollständigen Ausdruck:</p>
<pre><code class="language-cpp">int foo(int&amp; i) { return ++i; }
int i = 0;
int j = (i=0) + foo(i);
</code></pre>
<p>j ist garantiert 1; nicht etwa evtl. 2.</p>
<p>Bei List-Initialisierung werden die Initialisierer der einzelnen Elemente nacheinander ausgewertet. Das ist sogar dann der Fall (siehe Ausnahme zu 3.), wenn die List-Initialisierung zu einem Funktionsaufruf führt:</p>
<pre><code class="language-cpp">struct foo { foo(int, int) };
int x = 0;
foo{ x++, x++ };  // ruft den Konstruktor mit den Argumenten 0, 1 auf
foo( x++, x++ );  // ist undefiniert
</code></pre>
<p>Wahrscheinlich habe noch ein oder 2 Spezialsfälle vergessen - die sind dann aber wahrscheinlich auch praktisch ohne große Bedeutung.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2257902</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257902</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Sun, 07 Oct 2012 14:52:40 GMT</pubDate></item><item><title><![CDATA[Reply to Zuweisungen on Sun, 07 Oct 2012 14:51:28 GMT]]></title><description><![CDATA[<p>out schrieb:</p>
<blockquote>
<p>Stimmt. Dann muss man die Faustregel etwas strengen auslegen: Zwischen zwei sequence-points darf eine modifiziere Variable höchstens 1x auftauchen. Dann ist man wirklich safe, oder?</p>
</blockquote>
<p>Wenn ein Ausdruck vom Wert einer Variablen abhängt und diese Variable im gleichen Ausdruck auch modifiziert wird, muss die Leseoperation entweder dazu dienen, den zu speicherenden neuen Wert zu bestimmen, oder aber direkt vom modifizierenden Ausruck abhängen (=benutze die Zuweisung direkt als Operand). (Das ist ziemlich genau die Regel, wie sie in C++03 formuliert wurde).</p>
<pre><code class="language-cpp">int x = 1;
x = x + x + x + x; // ist ok
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2257904</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2257904</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Sun, 07 Oct 2012 14:51:28 GMT</pubDate></item></channel></rss>