<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://program.sonsuz.us/feed.xml" rel="self" type="application/atom+xml" /><link href="https://program.sonsuz.us/" rel="alternate" type="text/html" /><updated>2026-10-18T06:05:41+00:00</updated><id>https://program.sonsuz.us/feed.xml</id><title type="html">SonsuzUs</title><subtitle>Programlama ve Yazılım</subtitle><author><name>Sonsuz Us</name></author><entry><title type="html">C++ Şablonlarında Specialization ve Overloading: Derleyicinin İnce Seçim Oyunu</title><link href="https://program.sonsuz.us/posts/c-sablonlarinda-specialization-ve-overloading-derleyicinin-ince-secim-oyunu/" rel="alternate" type="text/html" title="C++ Şablonlarında Specialization ve Overloading: Derleyicinin İnce Seçim Oyunu" /><published>2026-10-18T00:00:00+00:00</published><updated>2026-10-18T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-sablonlarinda-specialization-ve-overloading-derleyicinin-ince-secim-oyunu</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-sablonlarinda-specialization-ve-overloading-derleyicinin-ince-secim-oyunu/"><![CDATA[<p><img src="/img/c-sablonlarinda-specialization-82.svg" alt="c-sablonlarinda-specialization-82" /></p>

<p>C++ şablonlarında özelleştirme ve aşırı yükleme aynı hedefe gidiyormuş gibi görünür: belirli türlerde farklı davranmak. Fakat derleyicinin gözünde bunlar iki ayrı mekanizmadır. Overloading adaylar arasındaki yarışı belirlerken specialization, yarışı kazanan şablonun özel bir sürümünün bulunup bulunmadığına bakar. Küçük görünen bu sıra farkı, şaşırtıcı sonuçların kaynağıdır.</p>

<p>``</p>

<h2 id="i̇ki-mekanizmanın-temel-anlamı">İki mekanizmanın temel anlamı</h2>

<p>Bir fonksiyon şablonunu aşırı yüklediğimizde derleyicinin aday listesine yeni bir fonksiyon şablonu ekleriz. Açık özelleştirme ise yeni ve bağımsız bir aday oluşturmaz; mevcut birincil şablonun belirli argümanlar için alternatif uygulamasını tanımlar.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="nc">T</span><span class="p">&gt;</span>
<span class="kt">void</span> <span class="nf">goster</span><span class="p">(</span><span class="n">T</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Genel sürüm</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">template</span><span class="o">&lt;</span><span class="p">&gt;</span>
<span class="kt">void</span> <span class="n">goster</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="kt">int</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"int özelleştirmesi</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="nc">T</span><span class="p">&gt;</span>
<span class="kt">void</span> <span class="nf">goster</span><span class="p">(</span><span class="n">T</span><span class="o">*</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"İşaretçi overload'u</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Burada üç bildirim varmış gibi görünse de overload çözümlemesinde yalnızca <code class="language-plaintext highlighter-rouge">goster(T)</code> ve <code class="language-plaintext highlighter-rouge">goster(T*)</code> yarışır. <code class="language-plaintext highlighter-rouge">goster&lt;int&gt;</code> ise ilk şablona bağlı bir açık özelleştirmedir.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Overloading</th>
      <th>Specialization</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Yeni aday oluşturur mu?</td>
      <td>Evet</td>
      <td>Hayır</td>
    </tr>
    <tr>
      <td>Fonksiyonlarda kısmi biçimi var mı?</td>
      <td>Overload ile benzetilebilir</td>
      <td>Hayır</td>
    </tr>
    <tr>
      <td>Seçim zamanı</td>
      <td>Overload çözümlemesi sırasında</td>
      <td>Birincil şablon seçildikten sonra</td>
    </tr>
    <tr>
      <td>Kapsam</td>
      <td>Fonksiyon ve normal fonksiyonlar</td>
      <td>Birincil şablona bağlı</td>
    </tr>
    <tr>
      <td>Temel amaç</td>
      <td>Farklı parametre biçimleri</td>
      <td>Belirli argüman için özel uygulama</td>
    </tr>
  </tbody>
</table>

<h2 id="derleyicinin-seçim-sırası">Derleyicinin seçim sırası</h2>

<p>Basitleştirilmiş süreç şöyledir:</p>

<ol>
  <li>Görünür fonksiyonlar ve fonksiyon şablonları aday kümeye alınır.</li>
  <li>Şablon argüman çıkarımı yapılır.</li>
  <li>Dönüşüm kalitesi ve şablonların kısmi sıralaması değerlendirilir.</li>
  <li>En iyi overload seçilir.</li>
  <li>Kazanan bir fonksiyon şablonuysa ona ait açık özelleştirme aranır.</li>
</ol>

<p>Bunu kabaca</p>

\[\text{çağrılacak fonksiyon} = \operatorname{specialization}(\operatorname{bestOverload}(C))\]

<p>şeklinde düşünebiliriz. Buradaki $C$, uygun adaylar kümesidir. İşlemlerin sırası ters değildir; specialization önce yarışıp overload’u yenemez.</p>

<h2 id="klasik-işaretçi-sürprizi">Klasik işaretçi sürprizi</h2>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span><span class="o">*</span> <span class="n">p</span> <span class="o">=</span> <span class="nb">nullptr</span><span class="p">;</span>
<span class="n">goster</span><span class="p">(</span><span class="n">p</span><span class="p">);</span>
</code></pre></div></div>

<p>İlk bakışta <code class="language-plaintext highlighter-rouge">T = int*</code> olduğundan genel şablonun <code class="language-plaintext highlighter-rouge">int*</code> özelleştirmesinin aranacağı düşünülebilir. Ancak <code class="language-plaintext highlighter-rouge">goster(T*)</code>, <code class="language-plaintext highlighter-rouge">int*</code> argümanı için <code class="language-plaintext highlighter-rouge">goster(T)</code> şablonundan daha özeldir. Dolayısıyla pointer overload’u yarışı kazanır. Derleyici artık yalnızca bu kazanan şablona bağlı bir explicit specialization olup olmadığına bakar; diğer birincil şablonun özelleştirmesine geri dönmez.</p>

<p>Bu nedenle bir specialization’ın hangi birincil şablona bağlı olduğu kritik önemdedir. Bildirim sırası ve specialization bildiriminin çağrıdan önce görünür olması da ayrı derleme birimlerinde ciddi farklar yaratabilir. Açık özelleştirme, örtük örneklemeye yol açan ilk kullanımdan önce bildirilmelidir.</p>

<h2 id="neden-fonksiyon-şablonları-kısmen-özelleştirilemez">Neden fonksiyon şablonları kısmen özelleştirilemez?</h2>

<p>Sınıf şablonlarında kısmi özelleştirme geçerlidir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="nc">T</span><span class="p">&gt;</span>
<span class="k">struct</span> <span class="nc">Bilgi</span><span class="p">;</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="nc">T</span><span class="p">&gt;</span>
<span class="k">struct</span> <span class="nc">Bilgi</span><span class="o">&lt;</span><span class="n">T</span><span class="o">*&gt;</span> <span class="p">{</span>
    <span class="k">static</span> <span class="k">constexpr</span> <span class="kt">bool</span> <span class="n">pointer</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Fakat aşağıdaki fonksiyon biçimi geçersizdir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="nc">T</span><span class="p">&gt;</span>
<span class="kt">void</span> <span class="n">isle</span><span class="o">&lt;</span><span class="n">T</span><span class="o">*&gt;</span><span class="p">(</span><span class="n">T</span><span class="o">*</span><span class="p">);</span> <span class="c1">// Geçersiz kısmi specialization</span>
</code></pre></div></div>

<p>Fonksiyonlarda aynı niyet overload ile ifade edilir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="nc">T</span><span class="p">&gt;</span>
<span class="kt">void</span> <span class="nf">isle</span><span class="p">(</span><span class="n">T</span><span class="o">*</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// Türetilen her işaretçi türü için ortak davranış</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bunun önemli nedeni, fonksiyonlarda zaten overload çözümlemesi bulunmasıdır. Kısmi specialization da eklenseydi iki ayrı sıralama sistemi birbiriyle çakışabilirdi.</p>

<h2 id="pratik-tercih-rehberi">Pratik tercih rehberi</h2>

<p>Bir tür ailesini yakalamak istiyorsanız overload kullanın. Yalnızca tek ve kesin bir şablon argümanı kombinasyonunda davranışı değiştirecekseniz explicit specialization düşünülebilir. Bununla birlikte fonksiyonlarda overload çoğu zaman daha okunabilir ve öngörülebilirdir.</p>

<p>Modern C++ kodunda <code class="language-plaintext highlighter-rouge">if constexpr</code>, kavramlar ve <code class="language-plaintext highlighter-rouge">requires</code> ifadeleri de güçlü alternatiflerdir. Özellikle kısıtlı overload’lar, niyeti doğrudan tür sistemi üzerinden anlatır. Altın kural şudur: specialization’ı bağımsız yarışmacı sanmayın; o, ancak bağlı olduğu şablon yarışı kazandığında sahneye çıkan yedek oyuncudur.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c++" /><category term="templates" /><category term="specialization" /><category term="overloading" /><category term="derleyici" /><category term="generic-programming" /><summary type="html"><![CDATA[C++ şablonlarında özelleştirme ve aşırı yükleme aynı hedefe gidiyormuş gibi görünür: belirli türlerde farklı davranmak. Fakat derleyicinin gözünde bunlar iki ayrı mekanizmadır. Overloading adaylar arasındaki yarışı belirlerken specialization, yarışı kazanan şablonun özel bir sürümünün bulunup bulunmadığına bakar. Küçük görünen bu sıra farkı, şaşırtıcı sonuçların kaynağıdır.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-sablonlarinda-specialization-82.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-sablonlarinda-specialization-82.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Fazladan Eklem, Fazladan Kaçış: Redundant Robot Kollarda Engel Atlama</title><link href="https://program.sonsuz.us/posts/fazladan-eklem-fazladan-kacis-redundant-robot-kollarda-engel-atlama/" rel="alternate" type="text/html" title="Fazladan Eklem, Fazladan Kaçış: Redundant Robot Kollarda Engel Atlama" /><published>2026-10-18T00:00:00+00:00</published><updated>2026-10-18T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/fazladan-eklem-fazladan-kacis-redundant-robot-kollarda-engel-atlama</id><content type="html" xml:base="https://program.sonsuz.us/posts/fazladan-eklem-fazladan-kacis-redundant-robot-kollarda-engel-atlama/"><![CDATA[<p>Bir robot kolunun görevi yalnızca hedefe ulaşmak değildir; bunu masaya, duvara veya merakla yaklaşan başka bir robota çarpmadan yapması gerekir. Redundant, yani artıklıklı çok eklemli kollar tam bu noktada avantaj sağlar. Uç efektörün konumu değişmeden dirseklerini ve diğer eklemlerini hareket ettirebilen bu robotlar, engeller karşısında adeta “hedefe bakarken belini büken” mekanik akrobatlara dönüşür.
``</p>
<h2 id="artıklılık-ne-anlama-gelir">Artıklılık ne anlama gelir?</h2>

<p>Bir manipülatörün eklem değişkenlerini $q \in R^n$, uç efektör görevini ise $x \in R^m$ ile gösterelim. İleri kinematik ilişki</p>

\[x = f(q)\]

<p>şeklindedir. Eğer eklem sayısı görev uzayının boyutundan büyükse, yani $n &gt; m$ ise sistem redundant kabul edilir. Örneğin üç boyutlu uzayda yalnızca uç noktanın konumunu kontrol etmek için üç bağımsız değişken yeterliyken yedi eklemli bir kol dört adet fazladan serbestlik derecesine sahiptir.</p>

<p>Bu fazlalık gereksiz değildir. Aynı uç efektör konumunu üreten birden fazla eklem yapılandırması bulunabilir. Robot böylece ana görevi bozmadan dirseğini bir engelden uzaklaştırabilir, eklem sınırlarından kaçabilir veya daha rahat bir duruş seçebilir.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Minimum serbestlikli kol</th>
      <th>Redundant kol</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Aynı hedef için çözüm</td>
      <td>Genellikle sınırlı</td>
      <td>Çok sayıda</td>
    </tr>
    <tr>
      <td>Engel çevresinde hareket</td>
      <td>Kısıtlı</td>
      <td>Esnek</td>
    </tr>
    <tr>
      <td>Eklem sınırlarından kaçış</td>
      <td>Zor</td>
      <td>İkincil görevle mümkün</td>
    </tr>
    <tr>
      <td>Hesaplama maliyeti</td>
      <td>Daha düşük</td>
      <td>Daha yüksek</td>
    </tr>
    <tr>
      <td>Arıza toleransı</td>
      <td>Düşük</td>
      <td>Görece yüksek</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/fazladan-eklem-fazladan-66.svg" alt="fazladan-eklem-fazladan-66" /></p>

<h2 id="jacobian-ve-sıfır-uzayı">Jacobian ve sıfır uzayı</h2>

<p>Eklem hızları ile uç efektör hızı arasındaki ilişki Jacobian matrisiyle kurulur:</p>

\[\dot{x} = J(q)\dot{q}\]

<p>Redundant bir sistemde ters çözüm tek değildir. Yaygın hız çözümü şöyledir:</p>

\[\dot{q} = J^+\dot{x} + (I-J^+J)z\]

<p>Burada $J^+$ Jacobian’ın sözde tersidir. İlk terim uç efektörü hedeflenen yönde hareket ettirir. İkinci terim ise Jacobian’ın sıfır uzayında kalır; başka bir deyişle uç efektör hareketini değiştirmeden eklemleri oynatır. Engel kaçınma sihrinin büyük bölümü bu ikinci terimdedir.</p>

<p>$z$ vektörü, robotu engelden uzaklaştıran bir maliyet fonksiyonunun negatif gradyanı olarak seçilebilir:</p>

\[z = -k \nabla H(q)\]

<p>$H(q)$ robot ile engel arasındaki mesafe azaldıkça büyüyen bir ceza fonksiyonu olabilir. Böylece robot bir eliyle hedefe ilerlerken “dirseğini içeri çekebilir.”</p>

<h2 id="basit-bir-hesaplama-örneği">Basit bir hesaplama örneği</h2>

<p>Aşağıdaki Python kodu, ana uç efektör hızına sıfır uzayı üzerinden ikincil bir kaçınma hareketi ekler:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">numpy</span> <span class="k">as</span> <span class="n">np</span>

<span class="k">def</span> <span class="nf">redundant_velocity</span><span class="p">(</span><span class="n">J</span><span class="p">,</span> <span class="n">target_velocity</span><span class="p">,</span> <span class="n">avoidance_gradient</span><span class="p">,</span> <span class="n">gain</span><span class="o">=</span><span class="mf">0.4</span><span class="p">):</span>
    <span class="n">J_pinv</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">linalg</span><span class="p">.</span><span class="nf">pinv</span><span class="p">(</span><span class="n">J</span><span class="p">)</span>
    <span class="n">identity</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">eye</span><span class="p">(</span><span class="n">J</span><span class="p">.</span><span class="n">shape</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>

    <span class="n">primary</span> <span class="o">=</span> <span class="n">J_pinv</span> <span class="o">@</span> <span class="n">target_velocity</span>
    <span class="n">null_space</span> <span class="o">=</span> <span class="n">identity</span> <span class="o">-</span> <span class="n">J_pinv</span> <span class="o">@</span> <span class="n">J</span>
    <span class="n">secondary</span> <span class="o">=</span> <span class="n">null_space</span> <span class="o">@</span> <span class="p">(</span><span class="o">-</span><span class="n">gain</span> <span class="o">*</span> <span class="n">avoidance_gradient</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">primary</span> <span class="o">+</span> <span class="n">secondary</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">primary</code> hedefe ulaşma görevini gerçekleştirir. <code class="language-plaintext highlighter-rouge">secondary</code> ise engel maliyetini azaltmaya çalışır. <code class="language-plaintext highlighter-rouge">null_space</code> izdüşümü sayesinde ikincil hareket, ideal matematiksel koşullarda uç efektörün istenen hızını bozmaz.</p>

<h2 id="potansiyel-alan-yaklaşımı">Potansiyel alan yaklaşımı</h2>

<p>Engeller çoğu zaman itici potansiyel alanlarla modellenir. Engel ile robot noktası arasındaki mesafe $d$, etkinin başladığı güvenli mesafe $d_0$ olsun:</p>

\[U(d) = \frac{1}{2}\eta\left(\frac{1}{d}-\frac{1}{d_0}\right)^2, \quad d &lt; d_0\]

<p>Robot engelden uzaktaysa ceza sıfırdır; yaklaştıkça hızla büyür. Bu yöntem sezgiseldir fakat yerel minimumlara takılabilir. Ayrıca yalnızca uç efektörü değil, dirsek ve bağlantılar üzerindeki örnek noktaları da kontrol etmek gerekir.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Avantaj</th>
      <th>Dezavantaj</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Potansiyel alan</td>
      <td>Hızlı ve sezgisel</td>
      <td>Yerel minimum oluşturabilir</td>
    </tr>
    <tr>
      <td>Sıfır uzayı kontrolü</td>
      <td>Ana görevi korur</td>
      <td>Tekilliklere duyarlıdır</td>
    </tr>
    <tr>
      <td>Optimizasyon tabanlı kontrol</td>
      <td>Kısıtları birlikte işler</td>
      <td>Daha fazla hesaplama ister</td>
    </tr>
  </tbody>
</table>

<p>Sonuç olarak fazladan serbestlik derecesi, robota yalnızca daha fazla hareket değil, aynı hedefe giderken daha iyi hareket seçme özgürlüğü verir. Doğru kontrol algoritmasıyla redundant kol; engellerden kaçınabilir, eklem sınırlarını koruyabilir ve çalışma alanında çok daha güvenli davranabilir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="robotik" /><category term="redundant manipülatör" /><category term="engel kaçınma" /><category term="ters kinematik" /><category term="jacobian" /><category term="optimizasyon" /><summary type="html"><![CDATA[Bir robot kolunun görevi yalnızca hedefe ulaşmak değildir; bunu masaya, duvara veya merakla yaklaşan başka bir robota çarpmadan yapması gerekir. Redundant, yani artıklıklı çok eklemli kollar tam bu noktada avantaj sağlar. Uç efektörün konumu değişmeden dirseklerini ve diğer eklemlerini hareket ettirebilen bu robotlar, engeller karşısında adeta “hedefe bakarken belini büken” mekanik akrobatlara dönüşür.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/fazladan-eklem-fazladan-66.png" /><media:content medium="image" url="https://program.sonsuz.us/img/fazladan-eklem-fazladan-66.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Java Operatörleri ve Kontrol İfadeleriyle Program Akışını Yönetmek</title><link href="https://program.sonsuz.us/posts/java-operatorleri-ve-kontrol-ifadeleriyle-program-akisini-yonetmek/" rel="alternate" type="text/html" title="Java Operatörleri ve Kontrol İfadeleriyle Program Akışını Yönetmek" /><published>2026-10-18T00:00:00+00:00</published><updated>2026-10-18T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/java-operatorleri-ve-kontrol-ifadeleriyle-program-akisini-yonetmek</id><content type="html" xml:base="https://program.sonsuz.us/posts/java-operatorleri-ve-kontrol-ifadeleriyle-program-akisini-yonetmek/"><![CDATA[<p>Bir Java programı yalnızca yukarıdan aşağıya çalışan komutlardan oluşsaydı, hesap makinesinden biraz daha heyecanlı uygulamalar geliştirmek zor olurdu. Operatörler verileri işlerken kontrol ifadeleri programın hangi yolu izleyeceğine karar verir. Başka bir deyişle operatörler soruları hazırlar, karar yapıları cevapları değerlendirir, döngüler ise gerekli işleri sabırla tekrarlar.
``</p>
<h2 id="operatörler-programın-hesaplama-araçları">Operatörler: Programın hesaplama araçları</h2>

<p>Operatörler, bir veya daha fazla değer üzerinde işlem yapan sembollerdir. Örneğin <code class="language-plaintext highlighter-rouge">+</code> toplama yaparken <code class="language-plaintext highlighter-rouge">&gt;</code> iki değeri karşılaştırır. Bir ifadenin sonucu başka bir operatörün girdisi olabilir. Bu nedenle işlem önceliğini anlamak önemlidir.</p>

<p>Örneğin aşağıdaki matematiksel ifade Java’da da aynı öncelik mantığıyla değerlendirilir:</p>

\[sonuc = 10 + 4 \times 2 = 18\]

<p>Çarpma önce çalışır. Sonucun <code class="language-plaintext highlighter-rouge">28</code> olması isteniyorsa parantez kullanılmalıdır: <code class="language-plaintext highlighter-rouge">(10 + 4) * 2</code>.</p>

<table>
  <thead>
    <tr>
      <th>Operatör grubu</th>
      <th>Örnekler</th>
      <th>Görevi</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Aritmetik</td>
      <td><code class="language-plaintext highlighter-rouge">+</code>, <code class="language-plaintext highlighter-rouge">-</code>, <code class="language-plaintext highlighter-rouge">*</code>, <code class="language-plaintext highlighter-rouge">/</code>, <code class="language-plaintext highlighter-rouge">%</code></td>
      <td>Matematiksel işlem yapar</td>
    </tr>
    <tr>
      <td>Karşılaştırma</td>
      <td><code class="language-plaintext highlighter-rouge">==</code>, <code class="language-plaintext highlighter-rouge">!=</code>, <code class="language-plaintext highlighter-rouge">&lt;</code>, <code class="language-plaintext highlighter-rouge">&gt;=</code></td>
      <td><code class="language-plaintext highlighter-rouge">boolean</code> sonuç üretir</td>
    </tr>
    <tr>
      <td>Mantıksal</td>
      <td><code class="language-plaintext highlighter-rouge">&amp;&amp;</code>, <code class="language-plaintext highlighter-rouge">||</code>, <code class="language-plaintext highlighter-rouge">!</code></td>
      <td>Koşulları birleştirir veya tersine çevirir</td>
    </tr>
    <tr>
      <td>Atama</td>
      <td><code class="language-plaintext highlighter-rouge">=</code>, <code class="language-plaintext highlighter-rouge">+=</code>, <code class="language-plaintext highlighter-rouge">-=</code></td>
      <td>Değişkene değer atar veya günceller</td>
    </tr>
    <tr>
      <td>Artırma-azaltma</td>
      <td><code class="language-plaintext highlighter-rouge">++</code>, <code class="language-plaintext highlighter-rouge">--</code></td>
      <td>Sayıyı bir artırır veya azaltır</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/java-operatorleri-ve-60.svg" alt="java-operatorleri-ve-60" /></p>

<p>Mod alma operatörü <code class="language-plaintext highlighter-rouge">%</code>, özellikle çift-tek kontrolünde kullanışlıdır. Bir $n$ sayısı için $n \bmod 2 = 0$ ise sayı çifttir.</p>

<h2 id="karar-yapıları-yol-ayrımındaki-java">Karar yapıları: Yol ayrımındaki Java</h2>

<p><code class="language-plaintext highlighter-rouge">if</code>, <code class="language-plaintext highlighter-rouge">else if</code> ve <code class="language-plaintext highlighter-rouge">else</code>, koşullara göre farklı kod blokları çalıştırır. Koşulun sonucu mutlaka <code class="language-plaintext highlighter-rouge">true</code> veya <code class="language-plaintext highlighter-rouge">false</code> olmalıdır.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">puan</span> <span class="o">=</span> <span class="mi">78</span><span class="o">;</span>

<span class="k">if</span> <span class="o">(</span><span class="n">puan</span> <span class="o">&gt;=</span> <span class="mi">85</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Pekiyi"</span><span class="o">);</span>
<span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">puan</span> <span class="o">&gt;=</span> <span class="mi">50</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Geçti"</span><span class="o">);</span>
<span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Kaldı"</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Bu kod, karşılaştırma operatörleriyle puanı sınıflandırır. Koşullar yukarıdan aşağıya sınanır ve ilk doğru bloğun ardından yapı sona erer. Dolayısıyla daha özel veya yüksek eşikli koşulların önce yazılması önemlidir.</p>

<p>Sabit seçeneklerin bulunduğu durumlarda <code class="language-plaintext highlighter-rouge">switch</code> daha okunaklı olabilir:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">String</span> <span class="n">rol</span> <span class="o">=</span> <span class="s">"editor"</span><span class="o">;</span>

<span class="k">switch</span> <span class="o">(</span><span class="n">rol</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">case</span> <span class="s">"admin"</span> <span class="o">-&gt;</span> <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Tam yetki"</span><span class="o">);</span>
    <span class="k">case</span> <span class="s">"editor"</span> <span class="o">-&gt;</span> <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"İçerik düzenleme yetkisi"</span><span class="o">);</span>
    <span class="k">default</span> <span class="o">-&gt;</span> <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Sınırlı yetki"</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>

<table>
  <thead>
    <tr>
      <th>Yapı</th>
      <th>En uygun kullanım</th>
      <th>Güçlü yönü</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">if-else</code></td>
      <td>Aralıklar ve karmaşık koşullar</td>
      <td>Esneklik</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">switch</code></td>
      <td>Belirli, ayrık seçenekler</td>
      <td>Okunabilirlik</td>
    </tr>
    <tr>
      <td>Üçlü operatör</td>
      <td>Kısa değer seçimi</td>
      <td>Az kod</td>
    </tr>
  </tbody>
</table>

<p>Üçlü operatörün biçimi <code class="language-plaintext highlighter-rouge">koşul ? doğruDeğer : yanlışDeğer</code> şeklindedir. Örneğin <code class="language-plaintext highlighter-rouge">yas &gt;= 18 ? "Yetişkin" : "Çocuk"</code> ifadesi kısa bir karar üretir; ancak iç içe kullanılırsa okunabilirliği hızla düşürür.</p>

<h2 id="döngüler-tekrarın-kontrollü-hâli">Döngüler: Tekrarın kontrollü hâli</h2>

<p>Döngüler, aynı işlemi belirli bir koşul sağlandığı sürece tekrarlar. <code class="language-plaintext highlighter-rouge">for</code> tekrar sayısı bilindiğinde, <code class="language-plaintext highlighter-rouge">while</code> koşul ön planda olduğunda, <code class="language-plaintext highlighter-rouge">do-while</code> ise bloğun en az bir kez çalışması gerektiğinde tercih edilir.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">toplam</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>

<span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="mi">5</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
    <span class="n">toplam</span> <span class="o">+=</span> <span class="n">i</span><span class="o">;</span>
<span class="o">}</span>

<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">toplam</span><span class="o">);</span> <span class="c1">// 15</span>
</code></pre></div></div>

<p>Bu döngü $1+2+3+4+5=15$ toplamını hesaplar. Başlangıç değeri, devam koşulu ve artış işlemi aynı satırda görüldüğü için akış kolayca izlenebilir.</p>

<p><code class="language-plaintext highlighter-rouge">break</code> döngüyü tamamen sonlandırırken <code class="language-plaintext highlighter-rouge">continue</code> yalnızca mevcut turu atlar. Bunlar güçlü araçlardır; gereğinden fazla kullanılmaları akışı takip etmeyi zorlaştırabilir.</p>

<h2 id="kısa-devre-değerlendirmesi">Kısa devre değerlendirmesi</h2>

<p>Mantıksal <code class="language-plaintext highlighter-rouge">&amp;&amp;</code> operatörü ilk koşul yanlışsa ikinci koşulu çalıştırmaz. <code class="language-plaintext highlighter-rouge">||</code> ise ilk koşul doğruysa devamını değerlendirmez:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="o">(</span><span class="n">kullanici</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">&amp;&amp;</span> <span class="n">kullanici</span><span class="o">.</span><span class="na">isActive</span><span class="o">())</span> <span class="o">{</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Giriş başarılı"</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Burada önce <code class="language-plaintext highlighter-rouge">null</code> kontrolü yapılır. Böylece var olmayan bir nesne üzerinde metot çağrılması ve <code class="language-plaintext highlighter-rouge">NullPointerException</code> oluşması engellenir.</p>

<p>Sonuç olarak operatörler veriyi dönüştürür, karar ifadeleri uygun yolu seçer ve döngüler tekrarları yönetir. Sağlam bir Java programında bu üçlü birlikte çalışır: doğru koşul kurulur, akış bilinçli biçimde yönlendirilir ve her tekrarın ne zaman biteceği açıkça tanımlanır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="java" /><category term="operatörler" /><category term="kontrol-akışı" /><category term="döngüler" /><category term="karar-yapıları" /><category term="programlama" /><summary type="html"><![CDATA[Bir Java programı yalnızca yukarıdan aşağıya çalışan komutlardan oluşsaydı, hesap makinesinden biraz daha heyecanlı uygulamalar geliştirmek zor olurdu. Operatörler verileri işlerken kontrol ifadeleri programın hangi yolu izleyeceğine karar verir. Başka bir deyişle operatörler soruları hazırlar, karar yapıları cevapları değerlendirir, döngüler ise gerekli işleri sabırla tekrarlar.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/java-operatorleri-ve-60.png" /><media:content medium="image" url="https://program.sonsuz.us/img/java-operatorleri-ve-60.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Robotikte A* ve RRT: Harita Okuyan Kâşif ile Rastgele Büyüyen Ağaç</title><link href="https://program.sonsuz.us/posts/robotikte-a-ve-rrt-harita-okuyan-kasif-ile-rastgele-buyuyen-agac/" rel="alternate" type="text/html" title="Robotikte A* ve RRT: Harita Okuyan Kâşif ile Rastgele Büyüyen Ağaç" /><published>2026-10-18T00:00:00+00:00</published><updated>2026-10-18T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/robotikte-a-ve-rrt-harita-okuyan-kasif-ile-rastgele-buyuyen-agac</id><content type="html" xml:base="https://program.sonsuz.us/posts/robotikte-a-ve-rrt-harita-okuyan-kasif-ile-rastgele-buyuyen-agac/"><![CDATA[<p>Bir robotun başlangıç noktasından hedefe gitmesi, düz bir çizgi çizmekten çok daha karmaşıktır. Duvarlar, hareket kısıtları, robotun boyutları ve bilinmeyen bölgeler devreye girdiğinde bir <strong>yol planlama algoritmasına</strong> ihtiyaç duyulur. A* ve RRT aynı soruya cevap arasa da bunu tamamen farklı biçimlerde yapar: A* düzenli bir haritada en umut verici hücreleri incelerken RRT, uzaya rastgele dallar uzatan meraklı bir ağaç gibi davranır.</p>

<p><img src="/img/robotikte-a-ve-74.svg" alt="robotikte-a-ve-74" /></p>

<p>``</p>

<h2 id="önce-problem-uzayını-tanıyalım">Önce problem uzayını tanıyalım</h2>

<p>Yol planlamada robotun bulunabileceği tüm durumlar <strong>konfigürasyon uzayı</strong>, yani $C$-space ile temsil edilir. İki boyutlu hareket eden noktasal bir robot için durum $(x,y)$ olabilir. Robotun yönü de önemliyse durum $(x,y,\theta)$ hâline gelir. Eklemli bir robot kolunda ise her eklem açısı yeni bir boyut ekler.</p>

<p>Engellerin kapladığı durumlar $C_{obs}$, güvenli durumlar ise $C_{free}$ olarak gösterilir. Amaç, başlangıç $q_{start}$ ile hedef $q_{goal}$ arasında tamamen $C_{free}$ içinde kalan bir yol bulmaktır.</p>

<p>A* çoğunlukla ayrıklaştırılmış grafiklerde çalışır. RRT ise sürekli ve yüksek boyutlu uzayları örnekleyerek grafik oluşturur. Temel ayrım burada başlar.</p>

<h2 id="a-maliyeti-ve-hedefi-birlikte-düşünmek">A*: Maliyeti ve hedefi birlikte düşünmek</h2>

<p>A*, incelenecek düğümleri şu puana göre seçer:</p>

\[f(n)=g(n)+h(n)\]

<p>Burada $g(n)$ başlangıçtan $n$ düğümüne kadar ödenen gerçek maliyet, $h(n)$ ise hedeften ne kadar uzakta olunduğunu tahmin eden sezgisel fonksiyondur. Izgara haritalarda Öklid uzaklığı $h(n)=\sqrt{(x_g-x_n)^2+(y_g-y_n)^2}$ olarak kullanılabilir.</p>

<p>Eğer $h(n)$ gerçek kalan maliyeti abartmıyorsa A*, en düşük maliyetli yolu bulmayı garanti eder. Ancak büyük veya çok boyutlu haritalarda bellekte tuttuğu açık ve kapalı düğüm kümeleri hızla büyüyebilir.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="n">heapq</span> <span class="kn">import</span> <span class="n">heappush</span><span class="p">,</span> <span class="n">heappop</span>

<span class="k">def</span> <span class="nf">astar</span><span class="p">(</span><span class="n">start</span><span class="p">,</span> <span class="n">goal</span><span class="p">,</span> <span class="n">neighbors</span><span class="p">,</span> <span class="n">heuristic</span><span class="p">):</span>
    <span class="n">queue</span> <span class="o">=</span> <span class="p">[(</span><span class="mi">0</span><span class="p">,</span> <span class="n">start</span><span class="p">)]</span>
    <span class="n">cost</span> <span class="o">=</span> <span class="p">{</span><span class="n">start</span><span class="p">:</span> <span class="mi">0</span><span class="p">}</span>
    <span class="n">parent</span> <span class="o">=</span> <span class="p">{</span><span class="n">start</span><span class="p">:</span> <span class="bp">None</span><span class="p">}</span>

    <span class="k">while</span> <span class="n">queue</span><span class="p">:</span>
        <span class="n">_</span><span class="p">,</span> <span class="n">current</span> <span class="o">=</span> <span class="nf">heappop</span><span class="p">(</span><span class="n">queue</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">current</span> <span class="o">==</span> <span class="n">goal</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">parent</span>

        <span class="k">for</span> <span class="n">nxt</span><span class="p">,</span> <span class="n">step_cost</span> <span class="ow">in</span> <span class="nf">neighbors</span><span class="p">(</span><span class="n">current</span><span class="p">):</span>
            <span class="n">new_cost</span> <span class="o">=</span> <span class="n">cost</span><span class="p">[</span><span class="n">current</span><span class="p">]</span> <span class="o">+</span> <span class="n">step_cost</span>
            <span class="k">if</span> <span class="n">nxt</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">cost</span> <span class="ow">or</span> <span class="n">new_cost</span> <span class="o">&lt;</span> <span class="n">cost</span><span class="p">[</span><span class="n">nxt</span><span class="p">]:</span>
                <span class="n">cost</span><span class="p">[</span><span class="n">nxt</span><span class="p">]</span> <span class="o">=</span> <span class="n">new_cost</span>
                <span class="n">priority</span> <span class="o">=</span> <span class="n">new_cost</span> <span class="o">+</span> <span class="nf">heuristic</span><span class="p">(</span><span class="n">nxt</span><span class="p">,</span> <span class="n">goal</span><span class="p">)</span>
                <span class="nf">heappush</span><span class="p">(</span><span class="n">queue</span><span class="p">,</span> <span class="p">(</span><span class="n">priority</span><span class="p">,</span> <span class="n">nxt</span><span class="p">))</span>
                <span class="n">parent</span><span class="p">[</span><span class="n">nxt</span><span class="p">]</span> <span class="o">=</span> <span class="n">current</span>
</code></pre></div></div>

<p>Bu sade uygulama, komşuları değerlendirerek en umut verici düğümü öncelik kuyruğundan seçer. Dönen <code class="language-plaintext highlighter-rouge">parent</code> sözlüğü geriye doğru izlenerek yol oluşturulur.</p>

<h2 id="rrt-boşluğa-rastgele-dallar-uzatmak">RRT: Boşluğa rastgele dallar uzatmak</h2>

<p>RRT başlangıç durumunu ağacın kökü yapar. Ardından uzaydan rastgele bir $q_{rand}$ noktası seçer, ağaçtaki en yakın $q_{near}$ düğümünü bulur ve ona doğru sınırlı bir adım atarak $q_{new}$ üretir. Bağlantı engelle çakışmıyorsa yeni düğüm ağaca eklenir.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">rrt</span><span class="p">(</span><span class="n">start</span><span class="p">,</span> <span class="n">goal</span><span class="p">,</span> <span class="n">sample</span><span class="p">,</span> <span class="n">nearest</span><span class="p">,</span> <span class="n">steer</span><span class="p">,</span> <span class="n">collision_free</span><span class="p">):</span>
    <span class="n">tree</span> <span class="o">=</span> <span class="p">[</span><span class="n">start</span><span class="p">]</span>
    <span class="n">parent</span> <span class="o">=</span> <span class="p">{</span><span class="n">start</span><span class="p">:</span> <span class="bp">None</span><span class="p">}</span>

    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="mi">5000</span><span class="p">):</span>
        <span class="n">random_state</span> <span class="o">=</span> <span class="nf">sample</span><span class="p">(</span><span class="n">goal</span><span class="p">)</span>
        <span class="n">near</span> <span class="o">=</span> <span class="nf">nearest</span><span class="p">(</span><span class="n">tree</span><span class="p">,</span> <span class="n">random_state</span><span class="p">)</span>
        <span class="n">new</span> <span class="o">=</span> <span class="nf">steer</span><span class="p">(</span><span class="n">near</span><span class="p">,</span> <span class="n">random_state</span><span class="p">)</span>

        <span class="k">if</span> <span class="nf">collision_free</span><span class="p">(</span><span class="n">near</span><span class="p">,</span> <span class="n">new</span><span class="p">):</span>
            <span class="n">tree</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">new</span><span class="p">)</span>
            <span class="n">parent</span><span class="p">[</span><span class="n">new</span><span class="p">]</span> <span class="o">=</span> <span class="n">near</span>
            <span class="k">if</span> <span class="nf">collision_free</span><span class="p">(</span><span class="n">new</span><span class="p">,</span> <span class="n">goal</span><span class="p">):</span>
                <span class="n">parent</span><span class="p">[</span><span class="n">goal</span><span class="p">]</span> <span class="o">=</span> <span class="n">new</span>
                <span class="k">return</span> <span class="n">parent</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">sample(goal)</code> zaman zaman doğrudan hedefi seçerse <strong>goal bias</strong> uygulanır ve arama hızlanabilir. RRT bir çözümü çabuk bulabilir; fakat bulunan yol genellikle zikzaklıdır ve en kısa yol garantisi yoktur. Bu nedenle sonradan yol yumuşatma yapılır veya asimptotik olarak optimum çözüme yaklaşan RRT* kullanılır.</p>

<h2 id="hızlı-karşılaştırma">Hızlı karşılaştırma</h2>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>A*</th>
      <th>RRT</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Arama biçimi</td>
      <td>Sistematik ve sezgisel</td>
      <td>Rastgele örnekleme</td>
    </tr>
    <tr>
      <td>Uzay</td>
      <td>Ayrık grafik/ızgara</td>
      <td>Sürekli konfigürasyon uzayı</td>
    </tr>
    <tr>
      <td>Optimumluk</td>
      <td>Uygun sezgiselle garantili</td>
      <td>Temel sürümde garantisiz</td>
    </tr>
    <tr>
      <td>Yüksek boyutlar</td>
      <td>Maliyetli</td>
      <td>Genellikle daha uygun</td>
    </tr>
    <tr>
      <td>Sonuç yolu</td>
      <td>Düzenli, maliyeti düşük</td>
      <td>Zikzaklı, yumuşatma gerektirebilir</td>
    </tr>
    <tr>
      <td>Tekrarlanabilirlik</td>
      <td>Genellikle aynı sonuç</td>
      <td>Rastgeleliğe bağlı</td>
    </tr>
  </tbody>
</table>

<h2 id="hangisini-seçmeli">Hangisini seçmeli?</h2>

<p>Depo robotu gibi iki boyutlu, bilinen bir maliyet haritasında çalışan sistemlerde A* güçlü ve öngörülebilir bir tercihtir. Robot kolu, insansız hava aracı veya karmaşık hareket kısıtları bulunan bir araç söz konusuysa RRT daha doğal olabilir. Pratik sistemler ikisini birleştirebilir: RRT ile uygulanabilir bir koridor bulunup A* veya optimizasyon yöntemleriyle yol iyileştirilebilir. Kısacası A* haritayı dikkatle okuyan bir kâşif, RRT ise hızla farklı yönlere dal uzatan bir öncüdür.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="robotik" /><category term="yol-planlama" /><category term="a-star" /><category term="rrt" /><category term="algoritma" /><category term="otonom-robotlar" /><summary type="html"><![CDATA[Bir robotun başlangıç noktasından hedefe gitmesi, düz bir çizgi çizmekten çok daha karmaşıktır. Duvarlar, hareket kısıtları, robotun boyutları ve bilinmeyen bölgeler devreye girdiğinde bir yol planlama algoritmasına ihtiyaç duyulur. A* ve RRT aynı soruya cevap arasa da bunu tamamen farklı biçimlerde yapar: A* düzenli bir haritada en umut verici hücreleri incelerken RRT, uzaya rastgele dallar uzatan meraklı bir ağaç gibi davranır.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/robotikte-a-ve-74.png" /><media:content medium="image" url="https://program.sonsuz.us/img/robotikte-a-ve-74.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Robotlar Görmeyi Nasıl Öğrenir? Etiketli Veri Darboğazı</title><link href="https://program.sonsuz.us/posts/robotlar-gormeyi-nasil-ogrenir-etiketli-veri-darbogazi/" rel="alternate" type="text/html" title="Robotlar Görmeyi Nasıl Öğrenir? Etiketli Veri Darboğazı" /><published>2026-10-18T00:00:00+00:00</published><updated>2026-10-18T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/robotlar-gormeyi-nasil-ogrenir-etiketli-veri-darbogazi</id><content type="html" xml:base="https://program.sonsuz.us/posts/robotlar-gormeyi-nasil-ogrenir-etiketli-veri-darbogazi/"><![CDATA[<p>Bir robotun masadaki bardağı tanıması bize son derece doğal görünebilir. Ancak robot için görüntü, anlamlı nesnelerden değil, sayısal piksel dizilerinden oluşur. Denetimli öğrenme bu sayılara anlam kazandırabilir; fakat bunun için binlerce, hatta milyonlarca doğru etiketlenmiş örnek gerekir. Robotik dünyasında bu gereksinim, algılama modellerinin önündeki en pahalı ve en inatçı engellerden biridir.
``</p>
<h2 id="denetimli-öğrenmenin-temel-mantığı">Denetimli öğrenmenin temel mantığı</h2>

<p>Denetimli öğrenmede model, giriş ve doğru çıktı çiftlerinden oluşan bir veri kümesiyle eğitilir. Bir kamera görüntüsü $x$, görüntüdeki nesnenin etiketi ise $y$ olsun. Modelin amacı, görüntüyü etikete dönüştüren yaklaşık bir $f_\theta$ fonksiyonu öğrenmektir:</p>

\[\hat{y} = f_\theta(x)\]

<p>Buradaki $\theta$, sinir ağının eğitim sırasında ayarlanan parametrelerini temsil eder. Model tahmini ile gerçek etiket arasındaki fark bir kayıp fonksiyonuyla ölçülür:</p>

\[\theta^* = \arg\min_\theta \frac{1}{N}\sum_{i=1}^{N} L(f_\theta(x_i), y_i)\]

<p>Kısacası model, yaptığı hataları azaltarak öğrenir. Fakat doğru cevapları gösteren $y_i$ etiketleri azsa, hatalıysa veya gerçek çalışma ortamını temsil etmiyorsa robot sağlam bir algı geliştiremez.</p>

<h2 id="robotikte-etiket-neden-pahalıdır">Robotikte etiket neden pahalıdır?</h2>

<p>İnternetteki kedi fotoğraflarını sınıflandırmak görece kolaydır. Robotik verilerde ise yalnızca “bu bir kutudur” demek yetmeyebilir. Kutunun piksel düzeyindeki sınırı, üç boyutlu konumu, yönelimi, uzaklığı ve tutulabilir bölgeleri de işaretlenebilir. LiDAR nokta bulutları, termal kameralar ve kuvvet sensörleri gibi farklı kaynaklar işi daha da zorlaştırır.</p>

<table>
  <thead>
    <tr>
      <th>Veri türü</th>
      <th>Gerekli etiket</th>
      <th>Başlıca zorluk</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>RGB görüntü</td>
      <td>Sınıf veya kutu</td>
      <td>Örtüşme ve ışık değişimi</td>
    </tr>
    <tr>
      <td>Segmentasyon</td>
      <td>Her pikselin sınıfı</td>
      <td>Çok yüksek işçilik</td>
    </tr>
    <tr>
      <td>Nokta bulutu</td>
      <td>3B kutu ve konum</td>
      <td>Uzman araç gereksinimi</td>
    </tr>
    <tr>
      <td>Robot kavrama</td>
      <td>Başarı, poz ve temas</td>
      <td>Fiziksel deneme maliyeti</td>
    </tr>
  </tbody>
</table>

<p>Üstelik fabrikada toplanan veriler, açık havada çalışan bir robotu temsil etmeyebilir. Bu durum <strong>dağılım kayması</strong> olarak adlandırılır. Eğitim verisi $P_{train}(x)$ ile gerçek ortam $P_{real}(x)$ farklı olduğunda yüksek laboratuvar başarısı sahada hızla düşebilir.</p>

<h2 id="az-etiketin-model-üzerindeki-etkileri">Az etiketin model üzerindeki etkileri</h2>

<p>Etiketli veri eksikliği yalnızca doğruluğu azaltmaz. Nadir nesneler yeterince görülmediği için sınıf dengesizliği oluşur. Model arka plan, renk veya ışık gibi yanıltıcı ipuçlarını ezberleyebilir. Yeni bir kamera açısı karşısında şaşırabilir ve belirsiz olduğu durumlarda bile aşırı güvenli tahminler üretebilir. Otonom araç veya cerrahi robot gibi güvenlik kritik sistemlerde bu, basit bir yazılım hatasından çok daha ciddi sonuçlar doğurur.</p>

<h2 id="darboğazı-aşma-yöntemleri">Darboğazı aşma yöntemleri</h2>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Avantaj</th>
      <th>Sınırlama</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Veri artırma</td>
      <td>Ucuz ve hızlıdır</td>
      <td>Yeni sahne bilgisi üretmez</td>
    </tr>
    <tr>
      <td>Sentetik veri</td>
      <td>Otomatik etiket sağlar</td>
      <td>Simülasyon-gerçeklik farkı vardır</td>
    </tr>
    <tr>
      <td>Aktif öğrenme</td>
      <td>Yalnızca faydalı örnekleri seçer</td>
      <td>Döngüsel insan katkısı ister</td>
    </tr>
    <tr>
      <td>Yarı denetimli öğrenme</td>
      <td>Etiketsiz veriyi kullanır</td>
      <td>Hatalı sözde etiket yayılabilir</td>
    </tr>
    <tr>
      <td>Transfer öğrenmesi</td>
      <td>Daha az veriyle başlanır</td>
      <td>Kaynak alan uyumsuz olabilir</td>
    </tr>
  </tbody>
</table>

<p>Aktif öğrenmede model, en kararsız olduğu görüntüleri insana gönderir. Aşağıdaki basitleştirilmiş örnek, en düşük güvene sahip tahminleri seçer:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">etiketlenecekleri_sec</span><span class="p">(</span><span class="n">model</span><span class="p">,</span> <span class="n">etiketsiz_veri</span><span class="p">,</span> <span class="n">adet</span><span class="o">=</span><span class="mi">20</span><span class="p">):</span>
    <span class="c1"># Her örnek için sınıf olasılıklarını hesaplar.
</span>    <span class="n">olasiliklar</span> <span class="o">=</span> <span class="n">model</span><span class="p">.</span><span class="nf">predict_proba</span><span class="p">(</span><span class="n">etiketsiz_veri</span><span class="p">)</span>

    <span class="c1"># En yüksek olasılık düşükse model kararsız kabul edilir.
</span>    <span class="n">guvenler</span> <span class="o">=</span> <span class="n">olasiliklar</span><span class="p">.</span><span class="nf">max</span><span class="p">(</span><span class="n">axis</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
    <span class="n">indeksler</span> <span class="o">=</span> <span class="n">guvenler</span><span class="p">.</span><span class="nf">argsort</span><span class="p">()[:</span><span class="n">adet</span><span class="p">]</span>
    <span class="k">return</span> <span class="n">indeksler</span>
</code></pre></div></div>

<p>Bu yöntem, her görüntüyü etiketlemek yerine öğrenmeye en fazla katkı sağlayacak örneklere odaklanır. Sentetik veriyle birleştiğinde maliyet daha da düşürülebilir. Alan rastgeleleştirme kullanılarak simülasyondaki ışık, doku, kamera açısı ve nesne konumu sürekli değiştirilir; böylece model tek bir yapay görünüme bağlanmaz.</p>

<h2 id="sonuç">Sonuç</h2>

<p>Robotik algılamanın sınırı çoğu zaman model mimarisi değil, verinin kalitesi ve çeşitliliğidir. Daha büyük bir sinir ağı, eksik dünya bilgisini sihirli biçimde tamamlayamaz. Başarılı sistemler; az sayıdaki kaliteli etiketi, bol miktarda etiketsiz veri, simülasyon, aktif öğrenme ve dikkatli saha testleriyle birleştirir. Robotlara görmeyi öğretirken asıl soru “Kaç görüntümüz var?” değil, “Bu görüntüler robotun karşılaşacağı dünyayı ne kadar iyi anlatıyor?” olmalıdır.</p>

<p><img src="/img/robotlar-gormeyi-nasil-55.svg" alt="robotlar-gormeyi-nasil-55" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="robotik" /><category term="denetimli öğrenme" /><category term="makine öğrenmesi" /><category term="bilgisayarlı görü" /><category term="veri etiketleme" /><category term="yapay zekâ" /><summary type="html"><![CDATA[Bir robotun masadaki bardağı tanıması bize son derece doğal görünebilir. Ancak robot için görüntü, anlamlı nesnelerden değil, sayısal piksel dizilerinden oluşur. Denetimli öğrenme bu sayılara anlam kazandırabilir; fakat bunun için binlerce, hatta milyonlarca doğru etiketlenmiş örnek gerekir. Robotik dünyasında bu gereksinim, algılama modellerinin önündeki en pahalı ve en inatçı engellerden biridir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/robotlar-gormeyi-nasil-55.png" /><media:content medium="image" url="https://program.sonsuz.us/img/robotlar-gormeyi-nasil-55.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Async Kodun Gizli Freni: Bloklayan Çağrılar Event Loop’u Nasıl Durdurur?</title><link href="https://program.sonsuz.us/posts/async-kodun-gizli-freni-bloklayan-cagrilar-event-loopu-nasil-durdurur/" rel="alternate" type="text/html" title="Async Kodun Gizli Freni: Bloklayan Çağrılar Event Loop’u Nasıl Durdurur?" /><published>2026-10-17T00:00:00+00:00</published><updated>2026-10-17T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/async-kodun-gizli-freni-bloklayan-cagrilar-event-loopu-nasil-durdurur</id><content type="html" xml:base="https://program.sonsuz.us/posts/async-kodun-gizli-freni-bloklayan-cagrilar-event-loopu-nasil-durdurur/"><![CDATA[<p>Python’da <code class="language-plaintext highlighter-rouge">async</code> ve <code class="language-plaintext highlighter-rouge">await</code> kullanmak, kodun otomatik olarak hızlı veya tamamen eşzamanlı çalışacağı anlamına gelmez. Asenkron bir fonksiyonun içine sıradan, bloklayan bir çağrı yerleştirirseniz diğer görevler beklemeye başlar. Tek şeritli bir yola park edilen kamyon gibi, küçücük görünen bu çağrı bütün event loop trafiğini durdurabilir.
``</p>

<h2 id="event-loop-gerçekte-ne-yapar">Event loop gerçekte ne yapar?</h2>

<p><code class="language-plaintext highlighter-rouge">asyncio</code> event loop, çalışmaya hazır görevleri sırayla ilerleten bir koordinatördür. Bir coroutine <code class="language-plaintext highlighter-rouge">await</code> ile kontrolü gönüllü biçimde bıraktığında loop başka bir göreve geçebilir. Buradaki kritik nokta şudur: Görev kontrolü bırakmazsa event loop onu zorla kenara çekmez.</p>

<p>Yaklaşık toplam bekleme süresini şöyle düşünebiliriz:</p>

\[T_{toplam} \approx \max(T_1, T_2, \ldots, T_n)\]

<p>Bu avantaj yalnızca görevler uygun noktalarda kontrolü event loop’a iade ederse geçerlidir. Bloklayan işlemler seri biçimde yürütülürse süre şu modele yaklaşır:</p>

\[T_{toplam} \approx \sum_{i=1}^{n} T_i\]

<table>
  <thead>
    <tr>
      <th>İşlem</th>
      <th style="text-align: right">Event loop’a kontrol verir mi?</th>
      <th>Sonuç</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">await asyncio.sleep(1)</code></td>
      <td style="text-align: right">Evet</td>
      <td>Diğer görevler çalışır</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">time.sleep(1)</code></td>
      <td style="text-align: right">Hayır</td>
      <td>Tüm loop bir saniye donar</td>
    </tr>
    <tr>
      <td>Asenkron HTTP isteği</td>
      <td style="text-align: right">Evet</td>
      <td>Ağ beklenirken görev değişir</td>
    </tr>
    <tr>
      <td>Senkron dosya veya HTTP çağrısı</td>
      <td style="text-align: right">Hayır</td>
      <td>İşlem bitene kadar loop bekler</td>
    </tr>
    <tr>
      <td>Yoğun CPU hesabı</td>
      <td style="text-align: right">Hayır</td>
      <td>İş parçacığı uzun süre meşgul kalır</td>
    </tr>
  </tbody>
</table>

<h2 id="masum-görünen-hata">Masum görünen hata</h2>

<p>Aşağıdaki örnekte fonksiyon <code class="language-plaintext highlighter-rouge">async</code> olsa da içindeki <code class="language-plaintext highlighter-rouge">time.sleep</code> bloklayıcıdır:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">asyncio</span>
<span class="kn">import</span> <span class="n">time</span>

<span class="k">async</span> <span class="k">def</span> <span class="nf">is_yap</span><span class="p">(</span><span class="n">no</span><span class="p">:</span> <span class="nb">int</span><span class="p">):</span>
    <span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">'</span><span class="si">{</span><span class="n">no</span><span class="si">}</span><span class="s"> başladı</span><span class="sh">'</span><span class="p">)</span>
    <span class="n">time</span><span class="p">.</span><span class="nf">sleep</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>  <span class="c1"># Event loop burada tamamen durur.
</span>    <span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">'</span><span class="si">{</span><span class="n">no</span><span class="si">}</span><span class="s"> bitti</span><span class="sh">'</span><span class="p">)</span>

<span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
    <span class="k">await</span> <span class="n">asyncio</span><span class="p">.</span><span class="nf">gather</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="nf">is_yap</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="mi">3</span><span class="p">)))</span>

<span class="n">asyncio</span><span class="p">.</span><span class="nf">run</span><span class="p">(</span><span class="nf">main</span><span class="p">())</span>
</code></pre></div></div>

<p>Üç görev oluşturulmasına rağmen yaklaşık altı saniye beklenir. Çünkü ilk görev <code class="language-plaintext highlighter-rouge">time.sleep(2)</code> çalıştırırken diğer coroutine’ler işlemciye ulaşamaz. Fonksiyon başındaki <code class="language-plaintext highlighter-rouge">async</code> ifadesi, içindeki senkron kodu sihirli biçimde asenkronlaştırmaz.</p>

<p>Uyku yalnızca beklemeyi temsil ediyorsa doğru çözüm <code class="language-plaintext highlighter-rouge">asyncio.sleep</code> kullanmaktır:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">async</span> <span class="k">def</span> <span class="nf">is_yap</span><span class="p">(</span><span class="n">no</span><span class="p">:</span> <span class="nb">int</span><span class="p">):</span>
    <span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">'</span><span class="si">{</span><span class="n">no</span><span class="si">}</span><span class="s"> başladı</span><span class="sh">'</span><span class="p">)</span>
    <span class="k">await</span> <span class="n">asyncio</span><span class="p">.</span><span class="nf">sleep</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>  <span class="c1"># Kontrol event loop'a geri verilir.
</span>    <span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">'</span><span class="si">{</span><span class="n">no</span><span class="si">}</span><span class="s"> bitti</span><span class="sh">'</span><span class="p">)</span>
</code></pre></div></div>

<p>Bu sürümde görevler birlikte ilerler ve toplam süre yaklaşık iki saniye olur.</p>

<h2 id="senkron-kütüphaneyi-çöpe-mi-atalım">Senkron kütüphaneyi çöpe mi atalım?</h2>

<p>Her bloklayan kütüphanenin asenkron alternatifi bulunmayabilir. Python 3.9 ve sonrasında <code class="language-plaintext highlighter-rouge">asyncio.to_thread</code>, bloklayan I/O işlemini ayrı bir iş parçacığında çalıştırmayı kolaylaştırır:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">asyncio</span>
<span class="kn">import</span> <span class="n">time</span>

<span class="k">def</span> <span class="nf">eski_raporu_uret</span><span class="p">():</span>
    <span class="n">time</span><span class="p">.</span><span class="nf">sleep</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
    <span class="k">return</span> <span class="sh">'</span><span class="s">Rapor hazır</span><span class="sh">'</span>

<span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
    <span class="n">sonuc</span> <span class="o">=</span> <span class="k">await</span> <span class="n">asyncio</span><span class="p">.</span><span class="nf">to_thread</span><span class="p">(</span><span class="n">eski_raporu_uret</span><span class="p">)</span>
    <span class="nf">print</span><span class="p">(</span><span class="n">sonuc</span><span class="p">)</span>

<span class="n">asyncio</span><span class="p">.</span><span class="nf">run</span><span class="p">(</span><span class="nf">main</span><span class="p">())</span>
</code></pre></div></div>

<p>Burada event loop beklerken donmaz; başka görevleri yürütmeye devam eder. Ancak <code class="language-plaintext highlighter-rouge">to_thread</code> özellikle dosya, ağ veya eski SDK çağrıları gibi I/O ağırlıklı işler için uygundur.</p>

<h2 id="cpu-ağırlıklı-işler-farklıdır">CPU ağırlıklı işler farklıdır</h2>

<p>Büyük görüntü işleme, asal sayı arama veya karmaşık veri dönüşümü gibi CPU ağırlıklı işler de event loop’u bloke eder. Bunları bir thread’e taşımak, Python’ın GIL davranışı nedeniyle her zaman gerçek paralellik sağlamaz. Böyle durumlarda <code class="language-plaintext highlighter-rouge">ProcessPoolExecutor</code> daha doğru seçim olabilir:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">asyncio</span>
<span class="kn">from</span> <span class="n">concurrent.futures</span> <span class="kn">import</span> <span class="n">ProcessPoolExecutor</span>

<span class="k">def</span> <span class="nf">agir_hesaplama</span><span class="p">(</span><span class="n">n</span><span class="p">:</span> <span class="nb">int</span><span class="p">):</span>
    <span class="k">return</span> <span class="nf">sum</span><span class="p">(</span><span class="n">i</span> <span class="o">*</span> <span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">n</span><span class="p">))</span>

<span class="k">async</span> <span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
    <span class="n">loop</span> <span class="o">=</span> <span class="n">asyncio</span><span class="p">.</span><span class="nf">get_running_loop</span><span class="p">()</span>
    <span class="k">with</span> <span class="nc">ProcessPoolExecutor</span><span class="p">()</span> <span class="k">as</span> <span class="n">havuz</span><span class="p">:</span>
        <span class="n">sonuc</span> <span class="o">=</span> <span class="k">await</span> <span class="n">loop</span><span class="p">.</span><span class="nf">run_in_executor</span><span class="p">(</span>
            <span class="n">havuz</span><span class="p">,</span> <span class="n">agir_hesaplama</span><span class="p">,</span> <span class="mi">20_000_000</span>
        <span class="p">)</span>
    <span class="nf">print</span><span class="p">(</span><span class="n">sonuc</span><span class="p">)</span>

<span class="n">asyncio</span><span class="p">.</span><span class="nf">run</span><span class="p">(</span><span class="nf">main</span><span class="p">())</span>
</code></pre></div></div>

<p>Kısacası <code class="language-plaintext highlighter-rouge">async/await</code>, bloklamayı ortadan kaldıran bir büyü değil, bekleme anlarını yönetme protokolüdür. Kod incelemesinde <code class="language-plaintext highlighter-rouge">time.sleep</code>, senkron HTTP istemcileri, ağır dosya işlemleri ve uzun döngüler özellikle aranmalıdır. Event loop’un sağlıklı kalmasının altın kuralı basittir: Ya kontrolü hızla geri verin ya da bloklayan işi uygun bir thread veya process havuzuna taşıyın.</p>

<p><img src="/img/async-kodun-gizli-69.svg" alt="async-kodun-gizli-69" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="python" /><category term="asyncio" /><category term="async-await" /><category term="event-loop" /><category term="eşzamanlılık" /><category term="performans" /><summary type="html"><![CDATA[Python’da async ve await kullanmak, kodun otomatik olarak hızlı veya tamamen eşzamanlı çalışacağı anlamına gelmez. Asenkron bir fonksiyonun içine sıradan, bloklayan bir çağrı yerleştirirseniz diğer görevler beklemeye başlar. Tek şeritli bir yola park edilen kamyon gibi, küçücük görünen bu çağrı bütün event loop trafiğini durdurabilir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/async-kodun-gizli-69.png" /><media:content medium="image" url="https://program.sonsuz.us/img/async-kodun-gizli-69.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C++ Akış ve Dosya G/Ç Sistemi: Verinin Yolculuğunu Yönetmek</title><link href="https://program.sonsuz.us/posts/c-akis-ve-dosya-gc-sistemi-verinin-yolculugunu-yonetmek/" rel="alternate" type="text/html" title="C++ Akış ve Dosya G/Ç Sistemi: Verinin Yolculuğunu Yönetmek" /><published>2026-10-17T00:00:00+00:00</published><updated>2026-10-17T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-akis-ve-dosya-gc-sistemi-verinin-yolculugunu-yonetmek</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-akis-ve-dosya-gc-sistemi-verinin-yolculugunu-yonetmek/"><![CDATA[<p>C++ programlarında veri bazen klavyeden gelir, bazen ekrana gider, bazen de bir dosyada yıllarca uyumayı bekler. Akış sistemi, verinin kaynağıyla hedefi arasındaki bu yolculuğu ortak ve nesne yönelimli bir arayüz üzerinden yönetir. Böylece geliştirici, klavye ile dosya arasında geçiş yaparken tamamen farklı yöntemler öğrenmek zorunda kalmaz.</p>

<p><img src="/img/c-akis-ve-62.svg" alt="c-akis-ve-62" /></p>

<p>``</p>

<h2 id="akış-mantığı-nedir">Akış Mantığı Nedir?</h2>

<p>Bir <strong>stream</strong>, sıralı biçimde taşınan karakter veya baytların oluşturduğu soyut bir kanaldır. Program çoğu zaman gerçek cihazla doğrudan ilgilenmez; akış nesnesine veri gönderir veya ondan veri ister. <code class="language-plaintext highlighter-rouge">std::cin</code>, <code class="language-plaintext highlighter-rouge">std::cout</code>, <code class="language-plaintext highlighter-rouge">std::cerr</code> ve dosya sınıfları bu yaklaşımın örnekleridir.</p>

<p>Akışların nesne yönelimli yapısı sınıf hiyerarşisine dayanır. <code class="language-plaintext highlighter-rouge">std::ios</code> biçimlendirme ve durum bilgisini taşırken <code class="language-plaintext highlighter-rouge">std::istream</code> okuma, <code class="language-plaintext highlighter-rouge">std::ostream</code> yazma davranışlarını sunar. <code class="language-plaintext highlighter-rouge">std::iostream</code> ise ikisini birleştirir. Dosya tarafındaki sınıflar aynı arayüzleri dosya tamponlarıyla ilişkilendirir.</p>

<table>
  <thead>
    <tr>
      <th>Sınıf</th>
      <th>Görevi</th>
      <th>Yaygın kullanım</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">std::ifstream</code></td>
      <td>Dosyadan okuma</td>
      <td>Yapılandırma yükleme</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">std::ofstream</code></td>
      <td>Dosyaya yazma</td>
      <td>Rapor veya günlük oluşturma</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">std::fstream</code></td>
      <td>Okuma ve yazma</td>
      <td>Kayıt güncelleme</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">std::stringstream</code></td>
      <td>Bellekte metin akışı</td>
      <td>Ayrıştırma ve dönüştürme</td>
    </tr>
  </tbody>
</table>

<p>Tamponlama, her küçük işlemde diske erişilmesini engeller. Kabaca toplam maliyet</p>

\[T \approx n \cdot t_{işlem} + k \cdot t_{G/Ç}\]

<p>şeklinde düşünülebilir. Tampon kullanıldığında pahalı G/Ç sayısı olan $k$ azalır. <code class="language-plaintext highlighter-rouge">flush</code> işlemi tamponu zorla hedefe aktarır; gereksiz kullanılması performansı düşürebilir.</p>

<h2 id="nesne-yönelimli-dosya-okuma-ve-yazma">Nesne Yönelimli Dosya Okuma ve Yazma</h2>

<p>Dosya nesneleri kaynak yönetimini <strong>RAII</strong> yaklaşımıyla gerçekleştirir. Nesne kapsamdan çıktığında dosya otomatik olarak kapatılır. Yine de açılışın başarılı olup olmadığını kontrol etmek gerekir.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;fstream&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;string&gt;</span><span class="cp">
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">ofstream</span> <span class="n">cikti</span><span class="p">(</span><span class="s">"notlar.txt"</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">ios</span><span class="o">::</span><span class="n">app</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">cikti</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">std</span><span class="o">::</span><span class="n">cerr</span> <span class="o">&lt;&lt;</span> <span class="s">"Dosya açılamadı!</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
        <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="n">cikti</span> <span class="o">&lt;&lt;</span> <span class="s">"Akışlar nesne yönelimlidir."</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Buradaki <code class="language-plaintext highlighter-rouge">std::ios::app</code>, yeni veriyi dosyanın sonuna ekler. Varsayılan davranışta <code class="language-plaintext highlighter-rouge">ofstream</code>, mevcut içeriği silebilir. Başlıca kipler şöyledir:</p>

<table>
  <thead>
    <tr>
      <th>Kip</th>
      <th>Anlamı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">std::ios::in</code></td>
      <td>Okuma için açar</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">std::ios::out</code></td>
      <td>Yazma için açar</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">std::ios::app</code></td>
      <td>Sona ekler</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">std::ios::trunc</code></td>
      <td>İçeriği temizler</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">std::ios::binary</code></td>
      <td>İkili kip kullanır</td>
    </tr>
  </tbody>
</table>

<p>Metin dosyasını satır satır okumak için <code class="language-plaintext highlighter-rouge">std::getline</code> güvenli ve anlaşılır bir seçimdir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">std</span><span class="o">::</span><span class="n">ifstream</span> <span class="nf">girdi</span><span class="p">(</span><span class="s">"notlar.txt"</span><span class="p">);</span>
<span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">satir</span><span class="p">;</span>

<span class="k">while</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">getline</span><span class="p">(</span><span class="n">girdi</span><span class="p">,</span> <span class="n">satir</span><span class="p">))</span> <span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">satir</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">if</span> <span class="p">(</span><span class="n">girdi</span><span class="p">.</span><span class="n">bad</span><span class="p">())</span> <span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cerr</span> <span class="o">&lt;&lt;</span> <span class="s">"Fiziksel bir okuma hatası oluştu.</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Döngü, okuma başarılı olduğu sürece çalışır. <code class="language-plaintext highlighter-rouge">while (!girdi.eof())</code> yaklaşımı önerilmez; çünkü EOF bayrağı ancak başarısız bir okuma denemesinden sonra etkinleşir.</p>

<h2 id="durum-bayrakları-ve-hata-yönetimi">Durum Bayrakları ve Hata Yönetimi</h2>

<p>Akış nesneleri kendi sağlık durumlarını saklar. <code class="language-plaintext highlighter-rouge">good()</code> sorun olmadığını, <code class="language-plaintext highlighter-rouge">eof()</code> dosya sonunu, <code class="language-plaintext highlighter-rouge">fail()</code> biçimsel veya mantıksal başarısızlığı, <code class="language-plaintext highlighter-rouge">bad()</code> ise daha ciddi G/Ç hatasını bildirir. Hata sonrasında <code class="language-plaintext highlighter-rouge">clear()</code> bayrakları sıfırlar; fakat hatalı karakterler hâlâ tampondaysa <code class="language-plaintext highlighter-rouge">ignore()</code> ile temizleme gerekebilir.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">sayi</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">cin</span> <span class="o">&gt;&gt;</span> <span class="n">sayi</span><span class="p">))</span> <span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cin</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cin</span><span class="p">.</span><span class="n">ignore</span><span class="p">(</span><span class="mi">10000</span><span class="p">,</span> <span class="sc">'\n'</span><span class="p">);</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Geçersiz sayı girdiniz.</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="konumlandırma-ve-i̇kili-dosyalar">Konumlandırma ve İkili Dosyalar</h2>

<p><code class="language-plaintext highlighter-rouge">tellg()</code> ve <code class="language-plaintext highlighter-rouge">tellp()</code> mevcut okuma-yazma konumunu verir; <code class="language-plaintext highlighter-rouge">seekg()</code> ve <code class="language-plaintext highlighter-rouge">seekp()</code> konumu değiştirir. Bu özellik büyük dosyalarda doğrudan belirli bir kayda erişmeyi sağlar. İkili dosyalar <code class="language-plaintext highlighter-rouge">read()</code> ve <code class="language-plaintext highlighter-rouge">write()</code> ile işlenebilir; ancak sınıfları ham baytlarla kaydetmek taşınabilir değildir. Dolgulama, endian düzeni ve işaretçi üyeleri sorun çıkarabilir. Kalıcı veriler için açık bir serileştirme biçimi tasarlamak daha güvenlidir.</p>

<p>Sonuç olarak C++ akış sistemi yalnızca dosya açıp kapatan bir araç değildir. Ortak arayüzler, durum yönetimi, tamponlama ve RAII sayesinde farklı veri kaynaklarını aynı zihinsel model altında birleştiren güçlü bir soyutlamadır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c++" /><category term="stream" /><category term="dosya işlemleri" /><category term="girdi çıktı" /><category term="oop" /><category term="fstream" /><summary type="html"><![CDATA[C++ programlarında veri bazen klavyeden gelir, bazen ekrana gider, bazen de bir dosyada yıllarca uyumayı bekler. Akış sistemi, verinin kaynağıyla hedefi arasındaki bu yolculuğu ortak ve nesne yönelimli bir arayüz üzerinden yönetir. Böylece geliştirici, klavye ile dosya arasında geçiş yaparken tamamen farklı yöntemler öğrenmek zorunda kalmaz.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-akis-ve-62.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-akis-ve-62.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C++ API Tasarımında Değer Semantiği mi, Referans Semantiği mi?</title><link href="https://program.sonsuz.us/posts/c-api-tasariminda-deger-semantigi-mi-referans-semantigi-mi/" rel="alternate" type="text/html" title="C++ API Tasarımında Değer Semantiği mi, Referans Semantiği mi?" /><published>2026-10-17T00:00:00+00:00</published><updated>2026-10-17T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-api-tasariminda-deger-semantigi-mi-referans-semantigi-mi</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-api-tasariminda-deger-semantigi-mi-referans-semantigi-mi/"><![CDATA[<p><img src="/img/c-api-tasariminda-87.svg" alt="c-api-tasariminda-87" /></p>

<p>Bir C++ API’sinin bir nesneyi kopyalaması mı, yoksa mevcut nesneye erişim sağlaması mı gerektiği küçük bir imza tercihi gibi görünebilir. Oysa bu karar; sahiplikten performansa, hata ayıklamadan eşzamanlılığa kadar bütün tasarımı etkiler. Kısacası <code class="language-plaintext highlighter-rouge">Widget</code> ile <code class="language-plaintext highlighter-rouge">Widget&amp;</code> arasındaki tek karakterlik fark, bazen bakım maliyetinde destan yazdırır.</p>

<p>``</p>

<h2 id="i̇ki-semantiğin-temel-fikri">İki semantiğin temel fikri</h2>

<p><strong>Değer semantiğinde</strong> değişken, bağımsız bir değeri temsil eder. Kopyalanan iki nesne başlangıçta eşit olabilir; ancak biri değiştirildiğinde diğeri etkilenmez. <code class="language-plaintext highlighter-rouge">int</code>, <code class="language-plaintext highlighter-rouge">std::string</code> ve <code class="language-plaintext highlighter-rouge">std::vector</code> bu modele iyi örneklerdir.</p>

<p><strong>Referans semantiğinde</strong> ise farklı değişkenler aynı nesnenin kimliğine erişebilir. Nesne üzerindeki değişiklikler tüm gözlemciler tarafından görülebilir. Burada önemli olan yalnızca içerik değil, nesnenin <em>hangi nesne</em> olduğudur.</p>

<p>Matematiksel olarak değer kopyalamayı şöyle düşünebiliriz:</p>

\[b = copy(a) \Rightarrow a = b\]

<p>Ancak sonradan <code class="language-plaintext highlighter-rouge">b</code> değiştirildiğinde genellikle:</p>

\[modify(b) \nRightarrow modify(a)\]

<p>Referanslarda ise <code class="language-plaintext highlighter-rouge">a</code> ve <code class="language-plaintext highlighter-rouge">b</code> aynı nesneyi gösteriyorsa durum farklıdır:</p>

\[identity(a) = identity(b) \Rightarrow modify(b) = modify(a)\]

<table>
  <thead>
    <tr>
      <th>Ölçüt</th>
      <th>Değer semantiği</th>
      <th>Referans semantiği</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Sahiplik</td>
      <td>Genellikle açık ve yerel</td>
      <td>Haricen yönetilebilir</td>
    </tr>
    <tr>
      <td>Bağımsızlık</td>
      <td>Kopyalar bağımsızdır</td>
      <td>Aynı nesne paylaşılabilir</td>
    </tr>
    <tr>
      <td>Yaşam süresi</td>
      <td>Değerin kapsamına bağlıdır</td>
      <td>Dangling riski taşır</td>
    </tr>
    <tr>
      <td>Değişiklik etkisi</td>
      <td>Yereldir</td>
      <td>Uzak kodu etkileyebilir</td>
    </tr>
    <tr>
      <td>Eşzamanlılık</td>
      <td>Daha kolay yönetilir</td>
      <td>Senkronizasyon gerekebilir</td>
    </tr>
    <tr>
      <td>Polimorfizm</td>
      <td>Nesne dilimleme riski vardır</td>
      <td>Doğal biçimde desteklenir</td>
    </tr>
  </tbody>
</table>

<h2 id="parametrelerde-seçimin-anlamı">Parametrelerde seçimin anlamı</h2>

<p>Bir fonksiyon parametresini değerle almak, fonksiyonun kendi bağımsız nesnesine sahip olacağını anlatır:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Report</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">void</span> <span class="n">addPage</span><span class="p">(</span><span class="kt">int</span> <span class="n">page</span><span class="p">);</span>
<span class="p">};</span>

<span class="kt">void</span> <span class="nf">archive</span><span class="p">(</span><span class="n">Report</span> <span class="n">report</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">report</span><span class="p">.</span><span class="n">addPage</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span>
    <span class="c1">// Çağıranın nesnesi değişmez.</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu yaklaşım özellikle fonksiyon nesneyi saklayacaksa veya dönüştürecekse kullanışlıdır. Çağıran geçici bir değer ya da <code class="language-plaintext highlighter-rouge">std::move</code> ile taşıma sağladığında gereksiz kopyalar azaltılabilir.</p>

<p>Salt okuma amaçlı büyük nesnelerde <code class="language-plaintext highlighter-rouge">const T&amp;</code>, kopyalama maliyetini önler:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">print</span><span class="p">(</span><span class="k">const</span> <span class="n">Report</span><span class="o">&amp;</span> <span class="n">report</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// report okunabilir fakat değiştirilemez.</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Buradaki <code class="language-plaintext highlighter-rouge">const</code>, sahiplik vermez; yalnızca bu erişim yolu üzerinden değişikliği engeller. Fonksiyon referansı saklıyorsa çağıranın nesnesi daha erken yok olabilir. API, bu yaşam süresi sözleşmesini açıkça belirtmelidir.</p>

<p>Değiştirilebilir <code class="language-plaintext highlighter-rouge">T&amp;</code> ise fonksiyonun çağıranın nesnesini değiştireceğini bildirir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">normalize</span><span class="p">(</span><span class="n">Report</span><span class="o">&amp;</span> <span class="n">report</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">report</span><span class="p">.</span><span class="n">addPage</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Böyle bir API etkili olsa da yan etki üretir. Sonuç döndüren değer tabanlı bir alternatif çoğu zaman daha anlaşılırdır:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Report</span> <span class="nf">normalized</span><span class="p">(</span><span class="n">Report</span> <span class="n">report</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">report</span><span class="p">.</span><span class="n">addPage</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">report</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Modern C++’ta taşıma semantiği ve kopya eleme sayesinde bu sürüm, göründüğünden daha ucuz olabilir. Yaklaşık maliyeti $C_{copy}$ yerine çoğu durumda $C_{move}$ veya doğrudan $0$ olur.</p>

<h2 id="dönüş-değerleri-ve-sahiplik">Dönüş değerleri ve sahiplik</h2>

<p>Yeni bir nesne üreten fonksiyonun <code class="language-plaintext highlighter-rouge">T</code> döndürmesi genellikle en güvenli seçenektir. <code class="language-plaintext highlighter-rouge">T&amp;</code> döndürmek ise var olan bir nesneye takma ad verir; nesnenin yaşam süresi çağıranın kullanımından uzun olmalıdır. Yerel değişkene referans döndürmek kesinlikle hatalıdır.</p>

<p>Paylaşılan kimlik gerçekten gerekliyse akıllı işaretçiler sözleşmeyi görünür kılar:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">std::unique_ptr&lt;T&gt;</code>: Tekil sahiplik aktarılır.</li>
  <li><code class="language-plaintext highlighter-rouge">std::shared_ptr&lt;T&gt;</code>: Sahiplik paylaşılır.</li>
  <li><code class="language-plaintext highlighter-rouge">std::weak_ptr&lt;T&gt;</code>: Sahip olmadan gözlem yapılır.</li>
  <li><code class="language-plaintext highlighter-rouge">T*</code> veya <code class="language-plaintext highlighter-rouge">T&amp;</code>: Genellikle sahip olunmayan erişim sunulur.</li>
</ul>

<h2 id="pratik-karar-rehberi">Pratik karar rehberi</h2>

<p>Para, koordinat, tarih ve yapılandırma gibi bağımsız kavramlarda değer semantiğini tercih edin. Veritabanı bağlantısı, pencere, cihaz, aktör veya polimorfik servis gibi kimliği önemli varlıklarda referans semantiği daha doğaldır.</p>

<p>API’nin davranışını şu sorularla sınayın: Nesne kopyalanınca anlam bozuluyor mu? Fonksiyon sahipliği devralıyor mu? Değişiklik çağırana yansımalı mı? Referansın geçerlilik süresi açık mı? Eşzamanlı erişim mümkün mü?</p>

<p>En iyi seçim her zaman en hızlı görünen seçenek değildir. İyi bir C++ API’si, sahiplik ve değişebilirlik niyetini tür sistemi üzerinden anlatır. Değer semantiği varsayılan güvenli liman; referans semantiği ise kimlik, paylaşım veya polimorfizm gerçekten gerektiğinde kullanılan güçlü ama dikkat isteyen araçtır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c++" /><category term="api tasarımı" /><category term="değer semantiği" /><category term="referans semantiği" /><category term="bellek yönetimi" /><category term="modern c++" /><summary type="html"><![CDATA[Bir C++ API’sinin bir nesneyi kopyalaması mı, yoksa mevcut nesneye erişim sağlaması mı gerektiği küçük bir imza tercihi gibi görünebilir. Oysa bu karar; sahiplikten performansa, hata ayıklamadan eşzamanlılığa kadar bütün tasarımı etkiler. Kısacası Widget ile Widget&amp; arasındaki tek karakterlik fark, bazen bakım maliyetinde destan yazdırır.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-api-tasariminda-87.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-api-tasariminda-87.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C Fonksiyonları: Argümanlardan Özyinelemeye Tekrar Kullanılabilir Kod</title><link href="https://program.sonsuz.us/posts/c-fonksiyonlari-argumanlardan-ozyinelemeye-tekrar-kullanilabilir-kod/" rel="alternate" type="text/html" title="C Fonksiyonları: Argümanlardan Özyinelemeye Tekrar Kullanılabilir Kod" /><published>2026-10-17T00:00:00+00:00</published><updated>2026-10-17T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-fonksiyonlari-argumanlardan-ozyinelemeye-tekrar-kullanilabilir-kod</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-fonksiyonlari-argumanlardan-ozyinelemeye-tekrar-kullanilabilir-kod/"><![CDATA[<p>C programlarında her işi <code class="language-plaintext highlighter-rouge">main</code> fonksiyonuna yüklemek, bütün eşyaları tek çekmeceye doldurmaya benzer: Başlangıçta kolay görünür, fakat aradığını bulmak kısa sürede işkenceye dönüşür. Fonksiyonlar, büyük problemleri adlandırılmış ve tekrar kullanılabilir küçük parçalara ayırır. Böylece kod daha okunabilir, test edilebilir ve değiştirilebilir hâle gelir.</p>

<p><img src="/img/c-fonksiyonlari-argumanlardan-91.svg" alt="c-fonksiyonlari-argumanlardan-91" /></p>

<p>``</p>

<h2 id="fonksiyonun-anatomisi">Fonksiyonun anatomisi</h2>

<p>Bir C fonksiyonu dönüş türü, ad, parametre listesi ve gövdeden oluşur. Fonksiyon kullanılmadan önce derleyicinin onun imzasını bilmesi gerekir. Bu nedenle prototipler çoğunlukla dosyanın üst bölümünde veya bir başlık dosyasında bulunur.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span>
<span class="kt">int</span> <span class="nf">maksimum</span><span class="p">(</span><span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">b</span><span class="p">);</span>  <span class="c1">// Fonksiyon prototipi</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="n">sonuc</span> <span class="o">=</span> <span class="n">maksimum</span><span class="p">(</span><span class="mi">12</span><span class="p">,</span> <span class="mi">7</span><span class="p">);</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"Büyük değer: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">sonuc</span><span class="p">);</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="nf">maksimum</span><span class="p">(</span><span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="p">(</span><span class="n">a</span> <span class="o">&gt;</span> <span class="n">b</span><span class="p">)</span> <span class="o">?</span> <span class="n">a</span> <span class="o">:</span> <span class="n">b</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">a</code> ve <code class="language-plaintext highlighter-rouge">b</code> birer <strong>parametre</strong>, çağrıdaki <code class="language-plaintext highlighter-rouge">12</code> ve <code class="language-plaintext highlighter-rouge">7</code> ise <strong>argümandır</strong>. <code class="language-plaintext highlighter-rouge">int</code> dönüş türü, fonksiyonun çağırana bir tam sayı göndereceğini belirtir. Değer döndürmeyen fonksiyonlarda <code class="language-plaintext highlighter-rouge">void</code> kullanılır.</p>

<table>
  <thead>
    <tr>
      <th>Kavram</th>
      <th>Görevi</th>
      <th>Örnek</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Prototip</td>
      <td>Fonksiyonun imzasını bildirir</td>
      <td><code class="language-plaintext highlighter-rouge">int maksimum(int, int);</code></td>
    </tr>
    <tr>
      <td>Parametre</td>
      <td>Fonksiyonun aldığı yerel değişkendir</td>
      <td><code class="language-plaintext highlighter-rouge">int a</code></td>
    </tr>
    <tr>
      <td>Argüman</td>
      <td>Çağrı sırasında gönderilen değerdir</td>
      <td><code class="language-plaintext highlighter-rouge">maksimum(12, 7)</code></td>
    </tr>
    <tr>
      <td>Dönüş değeri</td>
      <td>Sonucu çağırana iletir</td>
      <td><code class="language-plaintext highlighter-rouge">return a;</code></td>
    </tr>
  </tbody>
</table>

<h2 id="cde-argüman-aktarımı">C’de argüman aktarımı</h2>

<p>C, argümanları varsayılan olarak <strong>değer ile</strong> aktarır. Yani fonksiyon, özgün değişkenin kendisini değil kopyasını alır. Matematiksel olarak bunu $p = x$ biçiminde düşünebiliriz: <code class="language-plaintext highlighter-rouge">p</code> başlangıçta <code class="language-plaintext highlighter-rouge">x</code> ile aynı değere sahiptir, ancak ayrı bir saklama alanıdır.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">arttir</span><span class="p">(</span><span class="kt">int</span> <span class="n">sayi</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">sayi</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu fonksiyon çağıranın değişkenini değiştirmez. Kalıcı değişiklik için değişkenin adresi, yani bir işaretçi aktarılır:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">arttir</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="n">sayi</span><span class="p">)</span> <span class="p">{</span>
    <span class="p">(</span><span class="o">*</span><span class="n">sayi</span><span class="p">)</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="n">puan</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span>
    <span class="n">arttir</span><span class="p">(</span><span class="o">&amp;</span><span class="n">puan</span><span class="p">);</span>  <span class="c1">// puan artık 11</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">&amp;puan</code> değişkenin adresini verir; <code class="language-plaintext highlighter-rouge">*sayi</code> ise o adresteki değere erişir. Diziler fonksiyonlara gönderildiğinde ilk elemanlarının adresine dönüştükleri için yapılan değişiklikler özgün dizi üzerinde görülebilir.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Fonksiyona giden</th>
      <th style="text-align: right">Özgün veri değişir mi?</th>
      <th>Kullanım</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Değer aktarımı</td>
      <td>Verinin kopyası</td>
      <td style="text-align: right">Hayır</td>
      <td>Küçük ve salt okunur veriler</td>
    </tr>
    <tr>
      <td>İşaretçi aktarımı</td>
      <td>Bellek adresi</td>
      <td style="text-align: right">Evet</td>
      <td>Çıktı üretme, dizi veya yapı güncelleme</td>
    </tr>
  </tbody>
</table>

<p>İşaretçiler güçlüdür; fakat <code class="language-plaintext highlighter-rouge">NULL</code> adresler ve geçersiz bellek erişimleri kontrol edilmezse programı beklenmedik bir maceraya çıkarabilir.</p>

<h2 id="özyineleme-fonksiyonun-kendisini-çağırması">Özyineleme: Fonksiyonun kendisini çağırması</h2>

<p>Özyinelemeli bir fonksiyon problemi daha küçük bir örneğine dönüştürerek kendisini çağırır. Her özyinelemede iki parça zorunludur: çağrıları durduran <strong>taban durum</strong> ve problemi küçülten <strong>özyinelemeli adım</strong>.</p>

<p>Faktöriyel matematiksel olarak şöyle tanımlanır:</p>

\[n! = n \times (n-1)!, \quad 0! = 1\]

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">unsigned</span> <span class="kt">long</span> <span class="kt">long</span> <span class="nf">faktoriyel</span><span class="p">(</span><span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>              <span class="c1">// Taban durum</span>
        <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="n">n</span> <span class="o">*</span> <span class="n">faktoriyel</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">// Daha küçük problem</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">faktoriyel(4)</code> çağrısı, $4 \times 3 \times 2 \times 1$ sonucunu üretir. Her çağrı dönüş adresi ve yerel değişkenleriyle çağrı yığınına eklenir. Taban durum unutulursa çağrılar sürer ve sonunda <strong>stack overflow</strong> oluşabilir.</p>

<p>Bu örneğin zaman karmaşıklığı $T(n)=T(n-1)+O(1)$ olduğundan $O(n)$, çağrı yığını kullanımı da $O(n)$ olur. Döngülü sürüm aynı zaman karmaşıklığıyla genellikle $O(1)$ ek bellek tüketir. Buna karşılık ağaç dolaşma, böl-ve-yönet ve iç içe geçmiş yapılar özyineleme ile daha doğal ifade edilebilir.</p>

<p>Fonksiyon tasarlarken tek sorumluluk ilkesini benimsemek, açıklayıcı adlar seçmek ve gereksiz küresel değişkenlerden kaçınmak önemlidir. Kısacası fonksiyonlar yalnızca kod tekrarını azaltmaz; programın düşünce haritasını da oluşturur. İyi bölünmüş bir C programı, hem derleyicinin hem de gelecekteki sizin teşekkür edeceği bir programdır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c" /><category term="fonksiyonlar" /><category term="programlama" /><category term="özyineleme" /><category term="algoritma" /><category term="parametreler" /><summary type="html"><![CDATA[C programlarında her işi main fonksiyonuna yüklemek, bütün eşyaları tek çekmeceye doldurmaya benzer: Başlangıçta kolay görünür, fakat aradığını bulmak kısa sürede işkenceye dönüşür. Fonksiyonlar, büyük problemleri adlandırılmış ve tekrar kullanılabilir küçük parçalara ayırır. Böylece kod daha okunabilir, test edilebilir ve değiştirilebilir hâle gelir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-fonksiyonlari-argumanlardan-91.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-fonksiyonlari-argumanlardan-91.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C# Generics: Tür Güvenli ve Performanslı Koleksiyonların Sırrı</title><link href="https://program.sonsuz.us/posts/c-generics-tur-guvenli-ve-performansli-koleksiyonlarin-sirri/" rel="alternate" type="text/html" title="C# Generics: Tür Güvenli ve Performanslı Koleksiyonların Sırrı" /><published>2026-10-17T00:00:00+00:00</published><updated>2026-10-17T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-generics-tur-guvenli-ve-performansli-koleksiyonlarin-sirri</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-generics-tur-guvenli-ve-performansli-koleksiyonlarin-sirri/"><![CDATA[<p>Bir kutuya kalem koyup daha sonra içinden kahve kupası çıkarmayı beklemezsiniz. C# koleksiyonlarında da benzer bir düzen gerekir: Eklenen ve alınan değerlerin türü önceden bilinmelidir. Genel türler, yani <em>generics</em>, bu düzeni derleme zamanında sağlayarak çalışma anındaki sürpriz tür dönüşümü hatalarını azaltır ve özellikle değer türlerinde daha iyi performans sunar.</p>

<p>``</p>

<h2 id="generic-yapı-nedir">Generic yapı nedir?</h2>

<p>Generic yapı; sınıf, metot, arayüz veya temsilcinin çalışacağı veri türünü baştan sabitlemek yerine bir tür parametresiyle tanımlamaktır. En yaygın gösterim olan <code class="language-plaintext highlighter-rouge">T</code>, İngilizce <em>type</em> kelimesinden gelir; ancak zorunlu bir isim değildir.</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">Kutu</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="n">T</span> <span class="n">Deger</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>

    <span class="k">public</span> <span class="nf">Kutu</span><span class="p">(</span><span class="n">T</span> <span class="n">deger</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">Deger</span> <span class="p">=</span> <span class="n">deger</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kt">var</span> <span class="n">sayiKutusu</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Kutu</span><span class="p">&lt;</span><span class="kt">int</span><span class="p">&gt;(</span><span class="m">42</span><span class="p">);</span>
<span class="kt">var</span> <span class="n">metinKutusu</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Kutu</span><span class="p">&lt;</span><span class="kt">string</span><span class="p">&gt;(</span><span class="s">"Merhaba"</span><span class="p">);</span>
</code></pre></div></div>

<p>Burada aynı <code class="language-plaintext highlighter-rouge">Kutu&lt;T&gt;</code> sınıfı hem <code class="language-plaintext highlighter-rouge">int</code> hem de <code class="language-plaintext highlighter-rouge">string</code> ile kullanılabilir. Buna rağmen iki kutunun kuralları birbirinden ayrıdır. Örneğin <code class="language-plaintext highlighter-rouge">sayiKutusu.Deger</code> özelliğine metin atanması derleme aşamasında engellenir.</p>

<h2 id="eski-yaklaşım-ve-tür-güvenliği">Eski yaklaşım ve tür güvenliği</h2>

<p>Generic koleksiyonlardan önce farklı türleri saklamak için sıklıkla <code class="language-plaintext highlighter-rouge">ArrayList</code> kullanılırdı. Bu koleksiyon elemanları <code class="language-plaintext highlighter-rouge">object</code> olarak tuttuğu için hemen her şeyi kabul eder.</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="nn">System.Collections</span><span class="p">;</span>

<span class="kt">var</span> <span class="n">liste</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">ArrayList</span><span class="p">();</span>
<span class="n">liste</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="m">10</span><span class="p">);</span>
<span class="n">liste</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="s">"yirmi"</span><span class="p">);</span>

<span class="kt">int</span> <span class="n">toplam</span> <span class="p">=</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">liste</span><span class="p">[</span><span class="m">0</span><span class="p">]</span> <span class="p">+</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="n">liste</span><span class="p">[</span><span class="m">1</span><span class="p">];</span> <span class="c1">// Çalışma zamanı hatası</span>
</code></pre></div></div>

<p>Kod derlenir; fakat ikinci eleman <code class="language-plaintext highlighter-rouge">int</code> olmadığı için <code class="language-plaintext highlighter-rouge">InvalidCastException</code> oluşur. <code class="language-plaintext highlighter-rouge">List&lt;int&gt;</code> kullanıldığında yanlış değer daha program çalışmadan yakalanır:</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="n">sayilar</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p">&lt;</span><span class="kt">int</span><span class="p">&gt;();</span>
<span class="n">sayilar</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="m">10</span><span class="p">);</span>
<span class="c1">// sayilar.Add("yirmi"); // Derleme hatası</span>

<span class="kt">int</span> <span class="n">toplam</span> <span class="p">=</span> <span class="n">sayilar</span><span class="p">[</span><span class="m">0</span><span class="p">];</span> <span class="c1">// Dönüşüm gerekmiyor</span>
</code></pre></div></div>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th><code class="language-plaintext highlighter-rouge">ArrayList</code></th>
      <th><code class="language-plaintext highlighter-rouge">List&lt;T&gt;</code></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Eleman türü</td>
      <td><code class="language-plaintext highlighter-rouge">object</code></td>
      <td>Belirlenen <code class="language-plaintext highlighter-rouge">T</code></td>
    </tr>
    <tr>
      <td>Hata tespiti</td>
      <td>Çalışma zamanında</td>
      <td>Derleme zamanında</td>
    </tr>
    <tr>
      <td>Açık dönüşüm</td>
      <td>Genellikle gerekli</td>
      <td>Gerekli değil</td>
    </tr>
    <tr>
      <td>Değer türü maliyeti</td>
      <td>Boxing/unboxing olabilir</td>
      <td>Genellikle önlenir</td>
    </tr>
    <tr>
      <td>Kod okunabilirliği</td>
      <td>Daha düşük</td>
      <td>Daha yüksek</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/c-generics-tur-63.svg" alt="c-generics-tur-63" /></p>

<h2 id="performans-neden-artar">Performans neden artar?</h2>

<p><code class="language-plaintext highlighter-rouge">int</code>, <code class="language-plaintext highlighter-rouge">double</code> ve <code class="language-plaintext highlighter-rouge">bool</code> gibi değer türleri doğrudan değer taşır. Bunların <code class="language-plaintext highlighter-rouge">object</code> değişkenine yerleştirilmesine <strong>boxing</strong>, yeniden özgün türe çevrilmesine <strong>unboxing</strong> denir. Her boxing işlemi yönetilen bellekte ek bir nesne oluşturabilir ve dönüşüm maliyeti doğurabilir.</p>

<p>Basitleştirilmiş biçimde, $n$ elemanın boxing maliyeti $b$, unboxing maliyeti $u$ ise ek işlem yükü şöyle düşünülebilir:</p>

\[C_{eski} \approx n(b + u)\]

<p>Generic bir <code class="language-plaintext highlighter-rouge">List&lt;int&gt;</code> için bu dönüşümlerin çoğu ortadan kalktığından yaklaşık ek yük:</p>

\[C_{generic} \approx 0\]

<p>Gerçek performans donanıma, .NET sürümüne ve kullanım şekline bağlıdır; dolayısıyla bu eşitlik bir ölçüm değil, maliyet farkını anlatan zihinsel modeldir.</p>

<h2 id="generic-metotlar-ve-kısıtlar">Generic metotlar ve kısıtlar</h2>

<p>Generics yalnızca koleksiyonlara özgü değildir. Metotlar da tür parametresi alabilir:</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="n">T</span> <span class="n">IlkElemaniGetir</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;(</span><span class="n">IEnumerable</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;</span> <span class="n">kaynak</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">return</span> <span class="n">kaynak</span><span class="p">.</span><span class="nf">First</span><span class="p">();</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="n">ilkSayi</span> <span class="p">=</span> <span class="nf">IlkElemaniGetir</span><span class="p">(</span><span class="k">new</span><span class="p">[]</span> <span class="p">{</span> <span class="m">7</span><span class="p">,</span> <span class="m">8</span><span class="p">,</span> <span class="m">9</span> <span class="p">});</span>
<span class="kt">string</span> <span class="n">ilkAd</span> <span class="p">=</span> <span class="nf">IlkElemaniGetir</span><span class="p">(</span><span class="k">new</span><span class="p">[]</span> <span class="p">{</span> <span class="s">"Ada"</span><span class="p">,</span> <span class="s">"Linus"</span> <span class="p">});</span>
</code></pre></div></div>

<p>Bazen <code class="language-plaintext highlighter-rouge">T</code> tamamen serbest bırakılmamalıdır. <code class="language-plaintext highlighter-rouge">where</code> kısıtları, kabul edilen türlerin sahip olması gereken özellikleri belirtir:</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="n">T</span> <span class="n">YeniOlustur</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;()</span> <span class="k">where</span> <span class="n">T</span> <span class="p">:</span> <span class="k">class</span><span class="err">,</span> <span class="nc">new</span><span class="p">()</span>
<span class="p">{</span>
    <span class="k">return</span> <span class="k">new</span> <span class="nf">T</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Bu metot yalnızca referans türleriyle çalışır ve parametresiz kurucu ister. Yaygın kısıtlar arasında <code class="language-plaintext highlighter-rouge">class</code>, <code class="language-plaintext highlighter-rouge">struct</code>, <code class="language-plaintext highlighter-rouge">notnull</code>, <code class="language-plaintext highlighter-rouge">new()</code> ve belirli bir arayüz bulunur.</p>

<h2 id="hangi-koleksiyon-seçilmeli">Hangi koleksiyon seçilmeli?</h2>

<table>
  <thead>
    <tr>
      <th>İhtiyaç</th>
      <th>Generic koleksiyon</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Sıralı eleman listesi</td>
      <td><code class="language-plaintext highlighter-rouge">List&lt;T&gt;</code></td>
    </tr>
    <tr>
      <td>Anahtar-değer eşleşmesi</td>
      <td><code class="language-plaintext highlighter-rouge">Dictionary&lt;TKey, TValue&gt;</code></td>
    </tr>
    <tr>
      <td>Benzersiz elemanlar</td>
      <td><code class="language-plaintext highlighter-rouge">HashSet&lt;T&gt;</code></td>
    </tr>
    <tr>
      <td>İlk giren ilk çıkar</td>
      <td><code class="language-plaintext highlighter-rouge">Queue&lt;T&gt;</code></td>
    </tr>
    <tr>
      <td>Son giren ilk çıkar</td>
      <td><code class="language-plaintext highlighter-rouge">Stack&lt;T&gt;</code></td>
    </tr>
  </tbody>
</table>

<p>Generics; tekrar kullanılabilirliği, tür güvenliğini ve okunabilirliği aynı yapıda buluşturur. En önemli kazanç yalnızca hız değildir: Hataları kullanıcıya ulaşmadan derleyicide durdurmaktır. Kısacası <code class="language-plaintext highlighter-rouge">T</code>, küçük bir harf olsa da C# dünyasında oldukça büyük bir güvenlik görevlisidir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="csharp" /><category term="generics" /><category term="koleksiyonlar" /><category term="tür güvenliği" /><category term="performans" /><category term="dotnet" /><summary type="html"><![CDATA[Bir kutuya kalem koyup daha sonra içinden kahve kupası çıkarmayı beklemezsiniz. C# koleksiyonlarında da benzer bir düzen gerekir: Eklenen ve alınan değerlerin türü önceden bilinmelidir. Genel türler, yani generics, bu düzeni derleme zamanında sağlayarak çalışma anındaki sürpriz tür dönüşümü hatalarını azaltır ve özellikle değer türlerinde daha iyi performans sunar.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-generics-tur-63.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-generics-tur-63.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>