<?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[GCC Tail Call Optimization (?)]]></title><description><![CDATA[<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;

int factorial(int n) {
	int fac = 1;
	for (int i = 2; i &lt;= n; ++i)
		fac *= i;
	return fac;
}

int factorial2(int n) {
	return n &lt;= 1 ? 1 : factorial2(n-1) * n;
}

int factorial3(int n, int r = 1) {
	return n &lt;= 1 ? r : factorial3(n-1, n*r);
}

int main() {
	cout &lt;&lt; factorial(50000000) &lt;&lt; endl;
	cout &lt;&lt; factorial2(50000000) &lt;&lt; endl;
	cout &lt;&lt; factorial3(50000000) &lt;&lt; endl;
}
</code></pre>
<p>Wenn ich den Code mit g++ 4.5.2 compiliere, gibt es egal ob mit -O2, -Os oder -O3 ein keiner Stelle einen stack overflow.<br />
<strong>Kann jemand erklären, wie die Rekursion in factorial2 hier weg-optimiert wird?</strong></p>
<p>Unter g++ 4.2.1 allerdings wird die Rekusion in factorial2 nur mit -O2 weg-optimiert.<br />
Mit -Os oder -O3 gibt es in factorial2 einen stack overflow, nicht aber in factorial3. (Wie es meiner Meinung nach auch sein sollte?)</p>
<p>Ich suche ein Beispiel, an dem man gut zeigen kann, wozu man tail recursion braucht. Ist halt etwas doof, wenn dann g++ 4.5.2 daher kommt und die nicht-tail-recursive Funktion auch noch weg-optimiert. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/topic/292218/gcc-tail-call-optimization</link><generator>RSS for Node</generator><lastBuildDate>Mon, 17 Aug 2026 02:57:38 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/292218.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 05 Sep 2011 11:51:35 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to GCC Tail Call Optimization (?) on Mon, 05 Sep 2011 11:51:35 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;

int factorial(int n) {
	int fac = 1;
	for (int i = 2; i &lt;= n; ++i)
		fac *= i;
	return fac;
}

int factorial2(int n) {
	return n &lt;= 1 ? 1 : factorial2(n-1) * n;
}

int factorial3(int n, int r = 1) {
	return n &lt;= 1 ? r : factorial3(n-1, n*r);
}

int main() {
	cout &lt;&lt; factorial(50000000) &lt;&lt; endl;
	cout &lt;&lt; factorial2(50000000) &lt;&lt; endl;
	cout &lt;&lt; factorial3(50000000) &lt;&lt; endl;
}
</code></pre>
<p>Wenn ich den Code mit g++ 4.5.2 compiliere, gibt es egal ob mit -O2, -Os oder -O3 ein keiner Stelle einen stack overflow.<br />
<strong>Kann jemand erklären, wie die Rekursion in factorial2 hier weg-optimiert wird?</strong></p>
<p>Unter g++ 4.2.1 allerdings wird die Rekusion in factorial2 nur mit -O2 weg-optimiert.<br />
Mit -Os oder -O3 gibt es in factorial2 einen stack overflow, nicht aber in factorial3. (Wie es meiner Meinung nach auch sein sollte?)</p>
<p>Ich suche ein Beispiel, an dem man gut zeigen kann, wozu man tail recursion braucht. Ist halt etwas doof, wenn dann g++ 4.5.2 daher kommt und die nicht-tail-recursive Funktion auch noch weg-optimiert. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2115178</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2115178</guid><dc:creator><![CDATA[crt32]]></dc:creator><pubDate>Mon, 05 Sep 2011 11:51:35 GMT</pubDate></item><item><title><![CDATA[Reply to GCC Tail Call Optimization (?) on Mon, 05 Sep 2011 12:04:04 GMT]]></title><description><![CDATA[<p>crt32 schrieb:</p>
<blockquote>
<p>Ich suche ein Beispiel, an dem man gut zeigen kann, wozu man tail recursion braucht.</p>
</blockquote>
<p>Hast du hier nicht ein ziemlich gutes Beispiel gefunden? Das würde sonst sicher schiefgehen und wäre ziemlich lahm. So kann der Comoiler eine Schleife draus machen.</p>
<blockquote>
<p>Ist halt etwas doof, wenn dann g++ 4.5.2 daher kommt und die nicht-tail-recursive Funktion auch noch weg-optimiert. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /></p>
</blockquote>
<p>Entweder ist der g++ ziemlich gut im Umstellen von ausdrücken oder er rechnet alles schon zur Compilezeit aus. Schließlich ist schon bekannt, welche Werte auftreten werden. Nimm mal als Werte keine Compilezeitkonstanten sondern Benutzereingaben und gib dann richtig große Werte ein.</p>
<p>edit: Und da es, wie camper sagt, undefiniertes Verhalten ist, wird eventuell alles wegoptimiert. Nimm daher auch mal einen unsigned Datentyp, bei dem ist definiert, was bei Überlauf passiert.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2115189</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2115189</guid><dc:creator><![CDATA[SeppJ]]></dc:creator><pubDate>Mon, 05 Sep 2011 12:04:04 GMT</pubDate></item><item><title><![CDATA[Reply to GCC Tail Call Optimization (?) on Mon, 05 Sep 2011 12:02:14 GMT]]></title><description><![CDATA[<p>Dieses Programm hat sowieso undefiniertes Verhalten, weil es ziemlich schnell zu integer-Überläufen kommt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2115190</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2115190</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Mon, 05 Sep 2011 12:02:14 GMT</pubDate></item><item><title><![CDATA[Reply to GCC Tail Call Optimization (?) on Mon, 05 Sep 2011 12:28:53 GMT]]></title><description><![CDATA[<p><code>factorial2</code> ist rekursiv, kann aber sehr leicht vom Compiler in die endrekursive Variante umgeschrieben werden. Prinzipiell ist es ein <code>fold-right</code> ueber den natuerlichen Zahlen. Da die Multiplikation kommukativ ist, ist die Faltung von rechts aequivalent zur Faltung von links. Das erkennt und nutzt der Compiler. ... Falls du nur wenig verstanden hast, sollten in diesem Post genug Schluesselworte fuer google enthalten sein.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2115211</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2115211</guid><dc:creator><![CDATA[knivil]]></dc:creator><pubDate>Mon, 05 Sep 2011 12:28:53 GMT</pubDate></item><item><title><![CDATA[Reply to GCC Tail Call Optimization (?) on Mon, 05 Sep 2011 14:30:19 GMT]]></title><description><![CDATA[<p>SeppJ schrieb:</p>
<blockquote>
<p>crt32 schrieb:</p>
<blockquote>
<p>Ich suche ein Beispiel, an dem man gut zeigen kann, wozu man tail recursion braucht.</p>
</blockquote>
<p>Hast du hier nicht ein ziemlich gutes Beispiel gefunden? Das würde sonst sicher schiefgehen und wäre ziemlich lahm. So kann der Comoiler eine Schleife draus machen.</p>
</blockquote>
<p>Mir gings halt darum, zu sehen, dass die Implementierung ohne tail recursion einen stack overflow produziert und die andere nicht.</p>
<p>SeppJ schrieb:</p>
<blockquote>
<p>factorial2 ist rekursiv, kann aber sehr leicht vom Compiler in die endrekursive Variante umgeschrieben werden. Prinzipiell ist es ein fold-right ueber den natuerlichen Zahlen. Da die Multiplikation kommukativ ist, ist die Faltung von rechts aequivalent zur Faltung von links. Das erkennt und nutzt der Compiler.</p>
</blockquote>
<p>Danke, ich wusste nicht, dass der Compiler das erkennen kann.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2115309</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2115309</guid><dc:creator><![CDATA[crt32]]></dc:creator><pubDate>Mon, 05 Sep 2011 14:30:19 GMT</pubDate></item></channel></rss>