<?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-20T00:05:44+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 Göstericiler: Belleğin Adres Defterini Okumak</title><link href="https://program.sonsuz.us/posts/c-gostericiler-bellegin-adres-defterini-okumak/" rel="alternate" type="text/html" title="C Göstericiler: Belleğin Adres Defterini Okumak" /><published>2026-10-19T00:00:00+00:00</published><updated>2026-10-19T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-gostericiler-bellegin-adres-defterini-okumak</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-gostericiler-bellegin-adres-defterini-okumak/"><![CDATA[<p>C dilinde göstericiler, ilk karşılaşmada belleğin karanlık sokaklarında dolaşmak gibi görünebilir. Oysa bir gösterici yalnızca başka bir nesnenin bellekteki adresini saklayan değişkendir. Bu mekanizmayı kavradığınızda dizilerin, dinamik belleğin, fonksiyon parametrelerinin ve veri yapılarının neden bu kadar verimli çalıştığını da anlamaya başlarsınız.</p>

<p>``</p>

<h2 id="değer-değil-adres-saklamak">Değer Değil, Adres Saklamak</h2>

<p>Normal bir değişken doğrudan veri taşır. Gösterici ise bu verinin bulunduğu konumu taşır. Örneğin <code class="language-plaintext highlighter-rouge">int sayi = 42;</code> ifadesi bellekte bir tamsayı oluşturur. <code class="language-plaintext highlighter-rouge">&amp;sayi</code>, bu değişkenin adresini verir; <code class="language-plaintext highlighter-rouge">*ptr</code> ise göstericinin tuttuğu adrese giderek oradaki değere erişir.</p>

<table>
  <thead>
    <tr>
      <th>İfade</th>
      <th>Anlamı</th>
      <th>Örnek sonuç</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">sayi</code></td>
      <td>Değişkenin değeri</td>
      <td><code class="language-plaintext highlighter-rouge">42</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">&amp;sayi</code></td>
      <td>Değişkenin adresi</td>
      <td><code class="language-plaintext highlighter-rouge">0x7ffd...</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">ptr</code></td>
      <td>Göstericide saklanan adres</td>
      <td><code class="language-plaintext highlighter-rouge">0x7ffd...</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">*ptr</code></td>
      <td>Adresteki değer</td>
      <td><code class="language-plaintext highlighter-rouge">42</code></td>
    </tr>
  </tbody>
</table>

<p><img src="/img/c-gostericiler-bellegin-75.svg" alt="c-gostericiler-bellegin-75" /></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">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">sayi</span> <span class="o">=</span> <span class="mi">42</span><span class="p">;</span>
    <span class="kt">int</span> <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">sayi</span><span class="p">;</span>

    <span class="n">printf</span><span class="p">(</span><span class="s">"Deger: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">sayi</span><span class="p">);</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"Adres: %p</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span><span class="n">ptr</span><span class="p">);</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"Pointer uzerinden deger: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="o">*</span><span class="n">ptr</span><span class="p">);</span>

    <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="mi">99</span><span class="p">;</span> <span class="cm">/* Adresteki gerçek değeri değiştirir. */</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"Yeni deger: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">sayi</span><span class="p">);</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">int *ptr</code>, <code class="language-plaintext highlighter-rouge">ptr</code> değişkeninin bir <code class="language-plaintext highlighter-rouge">int</code> adresi taşıyacağını belirtir. <code class="language-plaintext highlighter-rouge">*ptr = 99</code> işlemi kopyayı değil, doğrudan <code class="language-plaintext highlighter-rouge">sayi</code> değişkenini değiştirir. Göstericilerin fonksiyonlara “dışarıdaki” veriyi değiştirme gücü vermesi de bu mantığa dayanır.</p>

<h2 id="bellek-ve-tür-bilgisi">Bellek ve Tür Bilgisi</h2>

<p>Bir adresi yalnızca sayı gibi düşünmek eksik kalır. Göstericinin türü, derleyiciye o adreste kaç baytlık ve nasıl yorumlanacak bir veri bulunduğunu söyler. Tipik bir sistemde <code class="language-plaintext highlighter-rouge">char</code> 1 bayt, <code class="language-plaintext highlighter-rouge">int</code> 4 bayt olabilir; ancak kesin boyutlar platforma bağlıdır ve <code class="language-plaintext highlighter-rouge">sizeof</code> ile öğrenilmelidir.</p>

<p>Bir dizinin başlangıç adresi $A$, eleman boyutu $s$ ve erişilecek indis $i$ olsun. İlgili elemanın adresi şu şekilde hesaplanır:</p>

\[\operatorname{adres}(dizi[i]) = A + i \times s\]

<p>Bu nedenle işaretçi aritmetiği sıradan tam sayı aritmetiğinden farklıdır. <code class="language-plaintext highlighter-rouge">ptr + 1</code>, adresi bir bayt değil, gösterilen türün boyutu kadar ilerletir.</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">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">sayilar</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">30</span><span class="p">,</span> <span class="mi">40</span><span class="p">};</span>
    <span class="kt">int</span> <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="n">sayilar</span><span class="p">;</span>

    <span class="k">for</span> <span class="p">(</span><span class="kt">size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">4</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">printf</span><span class="p">(</span><span class="s">"%zu: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="o">*</span><span class="p">(</span><span class="n">ptr</span> <span class="o">+</span> <span class="n">i</span><span class="p">));</span>
    <span class="p">}</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">*(ptr + i)</code> ile <code class="language-plaintext highlighter-rouge">ptr[i]</code> eşdeğerdir. Hatta <code class="language-plaintext highlighter-rouge">sayilar[i]</code> ifadesi de temelde başlangıç adresinden uygun miktarda ilerleyip değeri çözme işlemidir.</p>

<table>
  <thead>
    <tr>
      <th>İşlem</th>
      <th>Etki</th>
      <th>Güvenli kullanım</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">ptr++</code></td>
      <td>Sonraki elemana geçer</td>
      <td>Dizi sınırları içinde</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">ptr--</code></td>
      <td>Önceki elemana geçer</td>
      <td>Başlangıcın gerisine gitmeden</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">ptr2 - ptr1</code></td>
      <td>Eleman uzaklığını verir</td>
      <td>Aynı dizi üzerinde</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">ptr + i</code></td>
      <td><code class="language-plaintext highlighter-rouge">i</code> eleman ilerler</td>
      <td>Geçerli aralıkta</td>
    </tr>
  </tbody>
</table>

<h2 id="null-ve-tehlikeli-göstericiler">NULL ve Tehlikeli Göstericiler</h2>

<p>Başlatılmamış bir gösterici rastgele bir adres taşıyabilir. <code class="language-plaintext highlighter-rouge">NULL</code>, göstericinin geçerli bir nesneyi göstermediğini açıkça belirtir. Ancak <code class="language-plaintext highlighter-rouge">NULL</code> göstericiyi çözmek, yani <code class="language-plaintext highlighter-rouge">*ptr</code> kullanmak tanımsız davranıştır.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>

<span class="k">if</span> <span class="p">(</span><span class="n">ptr</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
    <span class="cm">/* Yalnızca geçerli adres varsa erişilir. */</span>
    <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Benzer şekilde yaşam süresi bitmiş yerel değişkenlerin adresleri ve <code class="language-plaintext highlighter-rouge">free</code> ile serbest bırakılmış bölgeleri gösteren işaretçiler “sarkan gösterici” oluşturur. Dizi sınırını aşmak da komşunun posta kutusunu kendi kutunuz sanmaya benzer: Adres vardır, fakat erişim hakkınız yoktur.</p>

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

<p>Göstericiler C’nin performans ve kontrol gücünün merkezindedir. <code class="language-plaintext highlighter-rouge">&amp;</code> adres alır, <code class="language-plaintext highlighter-rouge">*</code> adresteki veriyi çözer, tür bilgisi ise aritmetik adımların boyutunu belirler. Güvenli kullanım için göstericileri başlatmak, <code class="language-plaintext highlighter-rouge">NULL</code> kontrolü yapmak, nesnelerin yaşam süresini izlemek ve dizi sınırlarını korumak gerekir. Bu kurallar oturduğunda belleğin karanlık sokakları, tabelaları gayet okunaklı bir mahalleye dönüşür.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c" /><category term="göstericiler" /><category term="bellek" /><category term="pointer" /><category term="işaretçi-aritmetiği" /><category term="programlama" /><summary type="html"><![CDATA[C dilinde göstericiler, ilk karşılaşmada belleğin karanlık sokaklarında dolaşmak gibi görünebilir. Oysa bir gösterici yalnızca başka bir nesnenin bellekteki adresini saklayan değişkendir. Bu mekanizmayı kavradığınızda dizilerin, dinamik belleğin, fonksiyon parametrelerinin ve veri yapılarının neden bu kadar verimli çalıştığını da anlamaya başlarsınız.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-gostericiler-bellegin-75.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-gostericiler-bellegin-75.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C Önişlemci Komutları: Makrolar ve Koşullu Derleme Rehberi</title><link href="https://program.sonsuz.us/posts/c-onislemci-komutlari-makrolar-ve-kosullu-derleme-rehberi/" rel="alternate" type="text/html" title="C Önişlemci Komutları: Makrolar ve Koşullu Derleme Rehberi" /><published>2026-10-19T00:00:00+00:00</published><updated>2026-10-19T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-onislemci-komutlari-makrolar-ve-kosullu-derleme-rehberi</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-onislemci-komutlari-makrolar-ve-kosullu-derleme-rehberi/"><![CDATA[<p>C dilinde kaynak kod, doğrudan makine koduna çevrilmez; önce birkaç aşamadan geçen küçük bir yolculuğa çıkar. Önişlemci, bu yolculuğun derlemeden hemen önceki durağıdır. <code class="language-plaintext highlighter-rouge">#include</code>, <code class="language-plaintext highlighter-rouge">#define</code> ve <code class="language-plaintext highlighter-rouge">#if</code> gibi direktifleri işler; başlık dosyalarını ekler, makroları genişletir ve hangi kod parçalarının derleyiciye ulaşacağını belirler. Kısacası önişlemci, sahne açılmadan önce dekoru hazırlayan görünmez bir ekip gibidir.
``</p>

<h2 id="derlemeden-önce-neler-olur">Derlemeden önce neler olur?</h2>

<p>Tipik bir C programının üretim süreci kabaca dört aşamaya ayrılır:</p>

<table>
  <thead>
    <tr>
      <th>Aşama</th>
      <th>Girdi</th>
      <th>Yapılan işlem</th>
      <th>Çıktı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Önişleme</td>
      <td><code class="language-plaintext highlighter-rouge">.c</code> dosyası</td>
      <td>Direktifler ve makrolar işlenir</td>
      <td>Genişletilmiş kaynak kod</td>
    </tr>
    <tr>
      <td>Derleme</td>
      <td>Genişletilmiş kod</td>
      <td>C kodu assembly diline çevrilir</td>
      <td>Assembly kodu</td>
    </tr>
    <tr>
      <td>Assembly</td>
      <td>Assembly kodu</td>
      <td>Makine komutları oluşturulur</td>
      <td>Nesne dosyası</td>
    </tr>
    <tr>
      <td>Bağlama</td>
      <td>Nesne dosyaları</td>
      <td>Kütüphaneler birleştirilir</td>
      <td>Çalıştırılabilir program</td>
    </tr>
  </tbody>
</table>

<p>Bu süreci sembolik olarak şöyle gösterebiliriz:</p>

\[Kaynak \rightarrow Önişlemci \rightarrow Derleyici \rightarrow Assembler \rightarrow Bağlayıcı\]

<p>GCC kullanırken yalnızca önişlemci çıktısını görmek için şu komut çalıştırılabilir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gcc <span class="nt">-E</span> program.c <span class="nt">-o</span> program.i
</code></pre></div></div>

<p>Oluşan <code class="language-plaintext highlighter-rouge">program.i</code> dosyası genellikle oldukça uzundur; çünkü eklenen başlıkların içeriği de bu dosyada görünür.</p>

<h2 id="include-başlık-dosyalarını-eklemek"><code class="language-plaintext highlighter-rouge">#include</code>: Başlık dosyalarını eklemek</h2>

<p><code class="language-plaintext highlighter-rouge">#include</code>, belirtilen dosyanın içeriğini mevcut kaynak dosyaya metinsel olarak ekler:</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">
#include</span> <span class="cpf">"hesaplama.h"</span><span class="cp">
</span></code></pre></div></div>

<table>
  <thead>
    <tr>
      <th>Yazım</th>
      <th>Genel kullanım</th>
      <th>Arama davranışı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">&lt;stdio.h&gt;</code></td>
      <td>Standart veya sistem başlıkları</td>
      <td>Sistem başlık dizinleri aranır</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">"hesaplama.h"</code></td>
      <td>Projeye ait başlıklar</td>
      <td>Önce mevcut proje dizini aranır</td>
    </tr>
  </tbody>
</table>

<p>Aynı başlığın birden fazla kez eklenmesi tanım çakışmalarına yol açabilir. Bu nedenle include guard kullanılır:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#ifndef HESAPLAMA_H
#define HESAPLAMA_H
</span>
<span class="kt">int</span> <span class="nf">topla</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="cp">#endif
</span></code></pre></div></div>

<p>İlk eklemede <code class="language-plaintext highlighter-rouge">HESAPLAMA_H</code> tanımlanır. Sonraki eklemelerde <code class="language-plaintext highlighter-rouge">#ifndef</code> koşulu yanlış olacağı için dosyanın gövdesi atlanır.</p>

<h2 id="define-metinsel-dönüşüm-yapan-makrolar"><code class="language-plaintext highlighter-rouge">#define</code>: Metinsel dönüşüm yapan makrolar</h2>

<p>Nesne benzeri makrolar sabit değerleri temsil edebilir:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#define PI 3.141592653589793
#define MAKSIMUM_KULLANICI 100
</span></code></pre></div></div>

<p>Örneğin dairenin alanı $A = \pi r^2$ bağıntısıyla hesaplanabilir:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#define PI 3.141592653589793
#define KARE(x) ((x) * (x))
</span>
<span class="kt">double</span> <span class="nf">alan</span><span class="p">(</span><span class="kt">double</span> <span class="n">yaricap</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="n">PI</span> <span class="o">*</span> <span class="n">KARE</span><span class="p">(</span><span class="n">yaricap</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Parantezler önemlidir. <code class="language-plaintext highlighter-rouge">#define KARE(x) x * x</code> yazılsaydı <code class="language-plaintext highlighter-rouge">KARE(a + 1)</code> ifadesi <code class="language-plaintext highlighter-rouge">a + 1 * a + 1</code> biçiminde genişleyerek işlem önceliği hatası oluştururdu.</p>

<p>Makroların tür denetimi yapmadığı ve yalnızca metin değiştirdiği unutulmamalıdır. Ayrıca <code class="language-plaintext highlighter-rouge">KARE(i++)</code> gibi bir kullanım, argümanı iki kez değerlendirebilir. Bu durumda beklenmeyen yan etkiler ortaya çıkar. Tür güvenliği ve tek değerlendirme gerektiğinde <code class="language-plaintext highlighter-rouge">inline</code> fonksiyon genellikle daha iyi bir seçimdir.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Makro</th>
      <th><code class="language-plaintext highlighter-rouge">inline</code> fonksiyon</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Tür denetimi</td>
      <td>Yok</td>
      <td>Var</td>
    </tr>
    <tr>
      <td>Argüman değerlendirmesi</td>
      <td>Birden fazla olabilir</td>
      <td>Bir kez</td>
    </tr>
    <tr>
      <td>Çalıştığı aşama</td>
      <td>Önişleme</td>
      <td>Derleme</td>
    </tr>
    <tr>
      <td>Hata ayıklama</td>
      <td>Daha zor</td>
      <td>Daha kolay</td>
    </tr>
  </tbody>
</table>

<h2 id="koşullu-derleme">Koşullu derleme</h2>

<p>Koşullu direktifler, platforma veya yapılandırmaya göre farklı kodların derlenmesini sağlar:</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#ifdef DEBUG
</span>    <span class="n">printf</span><span class="p">(</span><span class="s">"Hata ayıklama modu etkin</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="cp">#endif
</span>
<span class="cp">#if defined(_WIN32)
</span>    <span class="n">printf</span><span class="p">(</span><span class="s">"Windows üzerinde çalışıyor</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="cp">#elif defined(__linux__)
</span>    <span class="n">printf</span><span class="p">(</span><span class="s">"Linux üzerinde çalışıyor</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="cp">#else
</span>    <span class="n">printf</span><span class="p">(</span><span class="s">"Bilinmeyen platform</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="cp">#endif
</span></code></pre></div></div>

<p>Komut satırından bir makro tanımlamak da mümkündür:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gcc <span class="nt">-DDEBUG</span> program.c <span class="nt">-o</span> program
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">#undef DEBUG</code> ise daha önce tanımlanmış makroyu kaldırır. Önişlemci ifadelerinde <code class="language-plaintext highlighter-rouge">defined</code>, mantıksal operatörler ve tamsayı sabitleri kullanılabilir; ancak normal C değişkenleri kullanılamaz. Çünkü değişkenler henüz derleyici tarafından işlenmemiştir.</p>

<p>Sonuç olarak C önişlemcisi güçlü fakat dikkatsiz kullanıldığında şaşırtıcıdır. Makroları küçük ve parantezli tutmak, include guard kullanmak, koşullu derlemeyi belgeli yürütmek ve mümkün olduğunda sabitler ile <code class="language-plaintext highlighter-rouge">inline</code> fonksiyonları tercih etmek daha okunabilir, taşınabilir ve güvenli programlar üretir.</p>

<p><img src="/img/c-onislemci-komutlari-51.svg" alt="c-onislemci-komutlari-51" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c" /><category term="önişlemci" /><category term="makro" /><category term="koşullu-derleme" /><category term="gcc" /><category term="programlama" /><summary type="html"><![CDATA[C dilinde kaynak kod, doğrudan makine koduna çevrilmez; önce birkaç aşamadan geçen küçük bir yolculuğa çıkar. Önişlemci, bu yolculuğun derlemeden hemen önceki durağıdır. #include, #define ve #if gibi direktifleri işler; başlık dosyalarını ekler, makroları genişletir ve hangi kod parçalarının derleyiciye ulaşacağını belirler. Kısacası önişlemci, sahne açılmadan önce dekoru hazırlayan görünmez bir ekip gibidir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-onislemci-komutlari-51.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-onislemci-komutlari-51.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C++ Şablonlar: Türlerden Bağımsız Jenerik Kod Yazmak</title><link href="https://program.sonsuz.us/posts/c-sablonlar-turlerden-bagimsiz-jenerik-kod-yazmak/" rel="alternate" type="text/html" title="C++ Şablonlar: Türlerden Bağımsız Jenerik Kod Yazmak" /><published>2026-10-19T00:00:00+00:00</published><updated>2026-10-19T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-sablonlar-turlerden-bagimsiz-jenerik-kod-yazmak</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-sablonlar-turlerden-bagimsiz-jenerik-kod-yazmak/"><![CDATA[<p>Aynı toplama, karşılaştırma veya sıralama işlemini <code class="language-plaintext highlighter-rouge">int</code>, <code class="language-plaintext highlighter-rouge">double</code> ve başka veri türleri için tekrar tekrar yazmak pek eğlenceli değildir. C++ şablonları, algoritmayı bir kez tanımlayıp onu farklı türlerle kullanmamızı sağlar. Böylece derleyici, ihtiyaç duyulan türe uygun kodu bizim için üretir; biz de kopyala-yapıştır bataklığından kurtuluruz.
``</p>
<h2 id="şablonların-temel-mantığı">Şablonların temel mantığı</h2>

<p>Şablon, henüz kesinleşmemiş bir türü veya değeri parametre olarak alan kod kalıbıdır. <code class="language-plaintext highlighter-rouge">T</code> gibi bir şablon parametresi başlangıçta gerçek bir tür değildir; derleme sırasında <code class="language-plaintext highlighter-rouge">int</code>, <code class="language-plaintext highlighter-rouge">double</code> veya kullanıcı tarafından tanımlanmış bir sınıfla değiştirilir.</p>

<p>Bunu matematikteki genel bir fonksiyona benzetebiliriz:</p>

\[f(x, y) = x + y\]

<p>Burada toplama işlemi, $x$ ve $y$ değerlerinin türünden çok <code class="language-plaintext highlighter-rouge">+</code> operatörünü destekleyip desteklemediğiyle ilgilenir. Şablonlar da benzer biçimde çalışır. Bir tür, şablonun kullandığı işlemleri sağlıyorsa o şablonla kullanılabilir.</p>

<table>
  <thead>
    <tr>
      <th>Yaklaşım</th>
      <th>Avantaj</th>
      <th>Dezavantaj</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Her tür için ayrı fonksiyon</td>
      <td>Okuması kolaydır</td>
      <td>Kod tekrarı oluşturur</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">void*</code> kullanımı</td>
      <td>Türden bağımsız görünebilir</td>
      <td>Tür güvenliği zayıftır</td>
    </tr>
    <tr>
      <td>Şablon kullanımı</td>
      <td>Tür güvenli ve yeniden kullanılabilirdir</td>
      <td>Hata mesajları karmaşık olabilir</td>
    </tr>
  </tbody>
</table>

<h2 id="fonksiyon-şablonları">Fonksiyon şablonları</h2>

<p>İki değerden büyük olanı döndüren jenerik bir fonksiyon yazalım:</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">
#include</span> <span class="cpf">&lt;string&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="n">T</span> <span class="nf">buyukOlan</span><span class="p">(</span><span class="k">const</span> <span class="n">T</span><span class="o">&amp;</span> <span class="n">a</span><span class="p">,</span> <span class="k">const</span> <span class="n">T</span><span class="o">&amp;</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>

<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">cout</span> <span class="o">&lt;&lt;</span> <span class="n">buyukOlan</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="o">&lt;&lt;</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="n">buyukOlan</span><span class="p">(</span><span class="mf">3.4</span><span class="p">,</span> <span class="mf">8.1</span><span class="p">)</span> <span class="o">&lt;&lt;</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="n">buyukOlan</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">(</span><span class="s">"Ali"</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">(</span><span class="s">"Zeynep"</span><span class="p">));</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">template &lt;typename T&gt;</code> ifadesi, <code class="language-plaintext highlighter-rouge">T</code> adlı bir tür parametresi tanımlar. Derleyici ilk çağrıda <code class="language-plaintext highlighter-rouge">T = int</code>, ikinci çağrıda <code class="language-plaintext highlighter-rouge">T = double</code> kabul eder. Bu işleme <strong>şablon örnekleme</strong> denir. Kabaca üretilen fonksiyon sayısını şöyle düşünebiliriz:</p>

\[N_{üretilen} \approx N_{benzersiz\ tür\ birleşimi}\]

<p>Parametreleri <code class="language-plaintext highlighter-rouge">const T&amp;</code> ile almak, özellikle büyük nesnelerin gereksiz yere kopyalanmasını önler. Ancak kullanılan türün <code class="language-plaintext highlighter-rouge">&gt;</code> operatörünü desteklemesi gerekir; aksi hâlde derleme hatası alınır.</p>

<h2 id="birden-fazla-tür-parametresi">Birden fazla tür parametresi</h2>

<p>Bazen giriş türleri birbirinden farklı olabilir:</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">,</span> <span class="k">typename</span> <span class="nc">U</span><span class="p">&gt;</span>
<span class="k">auto</span> <span class="nf">topla</span><span class="p">(</span><span class="k">const</span> <span class="n">T</span><span class="o">&amp;</span> <span class="n">a</span><span class="p">,</span> <span class="k">const</span> <span class="n">U</span><span class="o">&amp;</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</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="p">{</span>
    <span class="k">auto</span> <span class="n">sonuc</span> <span class="o">=</span> <span class="n">topla</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mf">2.5</span><span class="p">);</span> <span class="c1">// Sonuç double olur</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">auto</code> dönüş türünü <code class="language-plaintext highlighter-rouge">a + b</code> ifadesinden çıkarır. Böylece <code class="language-plaintext highlighter-rouge">int</code> ve <code class="language-plaintext highlighter-rouge">double</code> birlikte kullanılabilir. Yine de sonuç, ilgili türlerin birbirleriyle toplanabilmesine bağlıdır.</p>

<h2 id="sınıf-şablonları">Sınıf şablonları</h2>

<p>Şablonlar yalnızca fonksiyonlar için değildir. Farklı türlerde değer saklayabilen basit bir kutu sınıfı oluşturalım:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;utility&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="k">class</span> <span class="nc">Kutu</span> <span class="p">{</span>
<span class="nl">private:</span>
    <span class="n">T</span> <span class="n">deger</span><span class="p">;</span>

<span class="nl">public:</span>
    <span class="k">explicit</span> <span class="n">Kutu</span><span class="p">(</span><span class="n">T</span> <span class="n">yeniDeger</span><span class="p">)</span>
        <span class="o">:</span> <span class="n">deger</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">yeniDeger</span><span class="p">))</span> <span class="p">{}</span>

    <span class="k">const</span> <span class="n">T</span><span class="o">&amp;</span> <span class="n">getir</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span>
        <span class="k">return</span> <span class="n">deger</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="kt">void</span> <span class="nf">ayarla</span><span class="p">(</span><span class="k">const</span> <span class="n">T</span><span class="o">&amp;</span> <span class="n">yeniDeger</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">deger</span> <span class="o">=</span> <span class="n">yeniDeger</span><span class="p">;</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="p">{</span>
    <span class="n">Kutu</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">puan</span><span class="p">(</span><span class="mi">100</span><span class="p">);</span>
    <span class="n">Kutu</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">mesaj</span><span class="p">(</span><span class="s">"Merhaba şablon!"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">Kutu&lt;int&gt;</code> ve <code class="language-plaintext highlighter-rouge">Kutu&lt;std::string&gt;</code>, aynı sınıf şablonundan üretilmiş farklı sınıf türleridir. Derleyici bunların her biri için uygun alanları ve metotları oluşturur.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>Fonksiyon şablonu</th>
      <th>Sınıf şablonu</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Tür çıkarımı</td>
      <td>Genellikle otomatik</td>
      <td>Çoğunlukla açıkça belirtilir</td>
    </tr>
    <tr>
      <td>Kullanım amacı</td>
      <td>Jenerik algoritmalar</td>
      <td>Jenerik veri yapıları</td>
    </tr>
    <tr>
      <td>Örnek</td>
      <td><code class="language-plaintext highlighter-rouge">buyukOlan(3, 5)</code></td>
      <td><code class="language-plaintext highlighter-rouge">Kutu&lt;int&gt;</code></td>
    </tr>
  </tbody>
</table>

<h2 id="dikkat-edilmesi-gerekenler">Dikkat edilmesi gerekenler</h2>

<p>Şablon tanımları çoğunlukla başlık dosyalarında bulunur. Çünkü derleyicinin belirli bir tür için kod üretirken şablonun tüm gövdesini görmesi gerekir. Ayrıca her tür, şablonda kullanılan operatörleri sağlamalıdır. Modern C++20 projelerinde bu beklentiler <code class="language-plaintext highlighter-rouge">concept</code> yapılarıyla açıkça ifade edilebilir.</p>

<p>Şablonlar; <code class="language-plaintext highlighter-rouge">std::vector</code>, <code class="language-plaintext highlighter-rouge">std::map</code> ve <code class="language-plaintext highlighter-rouge">std::sort</code> gibi Standart Kütüphane araçlarının temelidir. Kısacası doğru kullanıldıklarında daha az tekrar, güçlü tür güvenliği ve genişletilebilir kod sunarlar. Derleyici biraz daha çalışır, fakat programcı çok daha az terler!</p>

<p><img src="/img/c-sablonlar-turlerden-70.svg" alt="c-sablonlar-turlerden-70" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c++" /><category term="templates" /><category term="jenerik programlama" /><category term="fonksiyon şablonları" /><category term="sınıf şablonları" /><category term="programlama" /><summary type="html"><![CDATA[Aynı toplama, karşılaştırma veya sıralama işlemini int, double ve başka veri türleri için tekrar tekrar yazmak pek eğlenceli değildir. C++ şablonları, algoritmayı bir kez tanımlayıp onu farklı türlerle kullanmamızı sağlar. Böylece derleyici, ihtiyaç duyulan türe uygun kodu bizim için üretir; biz de kopyala-yapıştır bataklığından kurtuluruz.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-sablonlar-turlerden-70.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-sablonlar-turlerden-70.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C# ve .NET Mimarisinin Temelleri: Kaynak Koddan CLR’a Yolculuk</title><link href="https://program.sonsuz.us/posts/c-ve-net-mimarisinin-temelleri-kaynak-koddan-clra-yolculuk/" rel="alternate" type="text/html" title="C# ve .NET Mimarisinin Temelleri: Kaynak Koddan CLR’a Yolculuk" /><published>2026-10-19T00:00:00+00:00</published><updated>2026-10-19T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/c-ve-net-mimarisinin-temelleri-kaynak-koddan-clra-yolculuk</id><content type="html" xml:base="https://program.sonsuz.us/posts/c-ve-net-mimarisinin-temelleri-kaynak-koddan-clra-yolculuk/"><![CDATA[<p>Bir C# programında <code class="language-plaintext highlighter-rouge">Console.WriteLine</code> yazıp çalıştır düğmesine bastığımızda perde arkasında küçük bir teknoloji festivali başlar. Kaynak kod derlenir, ara dile çevrilir, çalışma zamanı tarafından incelenir ve makine koduna dönüştürülür. C# ile .NET arasındaki ilişkiyi anlamak; performans, hata ayıklama ve taşınabilirlik gibi konuları ezberden değil, sağlam bir mimari üzerinden değerlendirmeyi sağlar.</p>

<p>``</p>

<h2 id="c-nereden-geldi">C# nereden geldi?</h2>

<p>C#, Microsoft tarafından .NET platformunun temel dillerinden biri olarak geliştirildi. Dilin baş mimarı Anders Hejlsberg’dir; ilk sürüm 2000 yılında duyurulmuş, .NET Framework ile birlikte 2002 yılında yaygın kullanıma açılmıştır. C++, Java ve Delphi gibi dillerden fikirler taşısa da zamanla kendine özgü, modern bir kimlik kazanmıştır.</p>

<p>C# başlangıçta Windows uygulamalarıyla özdeşleşse de günümüzde açık kaynaklı ve platformlar arası .NET üzerinde çalışır. Web uygulamalarından oyunlara, masaüstü yazılımlarından bulut servislerine kadar geniş bir kullanım alanına sahiptir.</p>

<table>
  <thead>
    <tr>
      <th>Kavram</th>
      <th>C#</th>
      <th>.NET</th>
      <th>CLR</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Temel görevi</td>
      <td>Programlama dili sunmak</td>
      <td>Geliştirme platformu sağlamak</td>
      <td>Kodu çalıştırmak</td>
    </tr>
    <tr>
      <td>İçeriği</td>
      <td>Sözdizimi ve dil kuralları</td>
      <td>Kütüphaneler, araçlar ve çalışma zamanı</td>
      <td>JIT, GC ve tür güvenliği</td>
    </tr>
    <tr>
      <td>Benzetme</td>
      <td>Tarif</td>
      <td>Mutfak</td>
      <td>Aşçı</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/c-ve-net-45.svg" alt="c-ve-net-45" /></p>

<p>Bu ayrım önemlidir: C# bir <strong>dildir</strong>, .NET bir <strong>platformdur</strong>, CLR ise bu platformun çalışma zamanı motorudur.</p>

<h2 id="derleme-süreci-nasıl-işler">Derleme süreci nasıl işler?</h2>

<p>C# kaynak kodu doğrudan işlemcinin anlayacağı makine koduna çevrilmez. Önce Roslyn derleyicisi tarafından <strong>Common Intermediate Language</strong> olarak bilinen CIL’e dönüştürülür. CIL, işlemciden büyük ölçüde bağımsız bir ara dildir. Derleme sonucunda <code class="language-plaintext highlighter-rouge">.dll</code> veya <code class="language-plaintext highlighter-rouge">.exe</code> uzantılı bir <strong>assembly</strong> oluşur.</p>

<p>Bir assembly yalnızca CIL komutlarını içermez. Türler, metotlar, sürüm bilgileri ve bağımlılıklar gibi <strong>metadata</strong> bilgilerini de taşır. Çalıştırma sırasında CLR içindeki Just-In-Time derleyicisi, ihtiyaç duyulan metotların CIL kodunu hedef işlemcinin makine koduna çevirir.</p>

<p>Süreci şöyle özetleyebiliriz:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>C# kaynak kodu
      ↓ Roslyn
CIL + metadata içeren assembly
      ↓ CLR ve JIT
Makine kodu
      ↓
İşlemci
</code></pre></div></div>

<p>Toplam çalışma maliyeti basitleştirilmiş biçimde şu şekilde düşünülebilir:</p>

\[T_{toplam} = T_{yükleme} + T_{JIT} + T_{çalıştırma}\]

<p>JIT maliyeti ilk çağrıda hissedilebilir; ancak üretilen yerel kod sonraki çağrılarda yeniden kullanılabilir. .NET ayrıca uygulamayı önceden yerel koda yaklaştıran ReadyToRun ve Native AOT gibi seçenekler de sunar.</p>

<h2 id="clr-hangi-işleri-üstlenir">CLR hangi işleri üstlenir?</h2>

<p>CLR, yalnızca kodu çalıştıran pasif bir katman değildir. Bellek yönetimi, hata işleme, güvenlik kontrolleri, iş parçacıkları ve tür güvenliği gibi sorumlulukları üstlenir. En bilinen bileşenlerinden biri <strong>Garbage Collector</strong>, yani çöp toplayıcıdır. Artık erişilemeyen nesnelerin belleğini otomatik olarak geri kazanır.</p>

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

<span class="k">public</span> <span class="k">sealed</span> <span class="k">class</span> <span class="nc">Urun</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="kt">string</span> <span class="n">Ad</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="p">}</span>
    <span class="k">public</span> <span class="kt">decimal</span> <span class="n">Fiyat</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="p">}</span>

    <span class="k">public</span> <span class="nf">Urun</span><span class="p">(</span><span class="kt">string</span> <span class="n">ad</span><span class="p">,</span> <span class="kt">decimal</span> <span class="n">fiyat</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">Ad</span> <span class="p">=</span> <span class="n">ad</span><span class="p">;</span>
        <span class="n">Fiyat</span> <span class="p">=</span> <span class="n">fiyat</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">public</span> <span class="kt">decimal</span> <span class="nf">KdvliFiyat</span><span class="p">(</span><span class="kt">decimal</span> <span class="n">oran</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="n">Fiyat</span> <span class="p">*</span> <span class="p">(</span><span class="m">1</span> <span class="p">+</span> <span class="n">oran</span><span class="p">);</span>
<span class="p">}</span>

<span class="kt">var</span> <span class="n">urun</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">Urun</span><span class="p">(</span><span class="s">"Klavye"</span><span class="p">,</span> <span class="m">1200m</span><span class="p">);</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="n">urun</span><span class="p">.</span><span class="nf">KdvliFiyat</span><span class="p">(</span><span class="m">0.20m</span><span class="p">));</span>
</code></pre></div></div>

<p>Bu örnekte <code class="language-plaintext highlighter-rouge">Urun</code> nesnesi yönetilen bellekte oluşturulur. CLR nesnenin yaşam döngüsünü izler; nesneye erişim kalmadığında ayrılan alan GC tarafından temizlenebilir. Geliştiricinin çoğu durumda belleği elle serbest bırakması gerekmez.</p>

<h2 id="cts-ve-cls-neden-önemlidir">CTS ve CLS neden önemlidir?</h2>

<p><strong>Common Type System</strong>, .NET dillerinin ortak tür modelini tanımlar. Örneğin C# dilindeki <code class="language-plaintext highlighter-rouge">int</code>, CLR düzeyinde <code class="language-plaintext highlighter-rouge">System.Int32</code> türüne karşılık gelir. <strong>Common Language Specification</strong> ise farklı .NET dillerinin birbiriyle uyumlu çalışabilmesi için takip etmesi gereken kuralları belirler.</p>

<table>
  <thead>
    <tr>
      <th>Bileşen</th>
      <th>Sağladığı avantaj</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>CIL</td>
      <td>İşlemci bağımsız ara temsil</td>
    </tr>
    <tr>
      <td>Metadata</td>
      <td>Tür ve bağımlılık bilgilerinin taşınması</td>
    </tr>
    <tr>
      <td>JIT</td>
      <td>Hedef sisteme uygun makine kodu</td>
    </tr>
    <tr>
      <td>GC</td>
      <td>Otomatik bellek yönetimi</td>
    </tr>
    <tr>
      <td>CTS ve CLS</td>
      <td>Diller arası uyumluluk</td>
    </tr>
  </tbody>
</table>

<p>Sonuç olarak C# kodu tek başına yolculuk etmez. Roslyn, CIL, assembly, JIT ve CLR katmanları birlikte çalışarak taşınabilir, güvenli ve yönetilebilir bir yürütme ortamı oluşturur. Bu mimariyi bilmek, yalnızca kod yazmayı değil, kodun gerçekte nasıl hayata geçtiğini de anlamaktır.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="csharp" /><category term="dotnet" /><category term="clr" /><category term="derleme" /><category term="jit" /><category term="programlama" /><summary type="html"><![CDATA[Bir C# programında Console.WriteLine yazıp çalıştır düğmesine bastığımızda perde arkasında küçük bir teknoloji festivali başlar. Kaynak kod derlenir, ara dile çevrilir, çalışma zamanı tarafından incelenir ve makine koduna dönüştürülür. C# ile .NET arasındaki ilişkiyi anlamak; performans, hata ayıklama ve taşınabilirlik gibi konuları ezberden değil, sağlam bir mimari üzerinden değerlendirmeyi sağlar.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/c-ve-net-45.png" /><media:content medium="image" url="https://program.sonsuz.us/img/c-ve-net-45.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Cron Çalışıyor Ama Script Çalışmıyor: PATH ve Ortam Değişkenleri Tuzağı</title><link href="https://program.sonsuz.us/posts/cron-calisiyor-ama-script-calismiyor-path-ve-ortam-degiskenleri-tuzagi/" rel="alternate" type="text/html" title="Cron Çalışıyor Ama Script Çalışmıyor: PATH ve Ortam Değişkenleri Tuzağı" /><published>2026-10-19T00:00:00+00:00</published><updated>2026-10-19T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/cron-calisiyor-ama-script-calismiyor-path-ve-ortam-degiskenleri-tuzagi</id><content type="html" xml:base="https://program.sonsuz.us/posts/cron-calisiyor-ama-script-calismiyor-path-ve-ortam-degiskenleri-tuzagi/"><![CDATA[<p>Terminalde kusursuz çalışan bir script’in cron tarafından başlatıldığında hata vermesi, Linux dünyasının klasik “ama benim makinemde çalışıyordu” vakalarındandır. Suç çoğu zaman cron’da değil; interaktif shell ile cron job’ının farklı <code class="language-plaintext highlighter-rouge">PATH</code>, çalışma dizini ve ortam değişkenleri kullanmasındadır.
``</p>
<h2 id="aynı-kullanıcı-neden-farklı-sonuç">Aynı kullanıcı, neden farklı sonuç?</h2>

<p>Terminal açtığımızda Bash genellikle <code class="language-plaintext highlighter-rouge">.bashrc</code>, <code class="language-plaintext highlighter-rouge">.profile</code> veya <code class="language-plaintext highlighter-rouge">.bash_profile</code> gibi başlangıç dosyalarını okuyabilir. Bu dosyalar <code class="language-plaintext highlighter-rouge">PATH</code>, dil ayarları, alias’lar ve uygulamalara özel değişkenler tanımlar. Cron ise öngörülebilir olmak amacıyla oldukça sade bir ortam oluşturur ve interaktif shell yapılandırmasını kendiliğinden yüklemez.</p>

<table>
  <thead>
    <tr>
      <th>Özellik</th>
      <th>İnteraktif shell</th>
      <th>Cron ortamı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">PATH</code></td>
      <td>Genellikle genişletilmiş</td>
      <td>Kısa ve sistem odaklı</td>
    </tr>
    <tr>
      <td>Başlangıç dosyaları</td>
      <td>Çoğunlukla okunur</td>
      <td>Genellikle okunmaz</td>
    </tr>
    <tr>
      <td>Çalışma dizini</td>
      <td>Kullanıcının seçtiği dizin</td>
      <td>Çoğu zaman kullanıcının ev dizini</td>
    </tr>
    <tr>
      <td>Alias ve fonksiyonlar</td>
      <td>Kullanılabilir</td>
      <td>Genellikle tanımsız</td>
    </tr>
    <tr>
      <td>TTY</td>
      <td>Vardır</td>
      <td>Yoktur</td>
    </tr>
    <tr>
      <td>Dil değişkenleri</td>
      <td>Kullanıcı ayarlarından gelir</td>
      <td>Eksik veya farklı olabilir</td>
    </tr>
  </tbody>
</table>

<p><img src="/img/cron-calisiyor-ama-55.svg" alt="cron-calisiyor-ama-55" /></p>

<p>Shell bir komutun içinde <code class="language-plaintext highlighter-rouge">/</code> görmezse çalıştırılabilir dosyayı <code class="language-plaintext highlighter-rouge">PATH</code> dizinlerinde sırayla arar. Bunu basitçe şöyle düşünebiliriz:</p>

\[\text{komut yolu} = \min\{d_i/komut \mid d_i \in PATH,\; çalıştırılabilir\}\]

<p>Örneğin terminalinizde <code class="language-plaintext highlighter-rouge">/usr/local/bin</code> mevcutken cron’un <code class="language-plaintext highlighter-rouge">PATH</code> değerinde bu dizin yoksa <code class="language-plaintext highlighter-rouge">node</code>, <code class="language-plaintext highlighter-rouge">python</code>, <code class="language-plaintext highlighter-rouge">docker</code> veya özel bir CLI bulunamayabilir. Sonuç genellikle <code class="language-plaintext highlighter-rouge">command not found</code> olur; çıktı yönlendirilmediyse hatayı görmeyebilirsiniz bile.</p>

<h2 id="güvenilir-çözüm-ortamı-açıkça-tanımlamak">Güvenilir çözüm: ortamı açıkça tanımlamak</h2>

<p>Crontab içinde ihtiyaç duyulan shell ve <code class="language-plaintext highlighter-rouge">PATH</code> değerlerini belirtmek ilk savunma hattıdır:</p>

<pre><code class="language-cron">SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin

*/10 * * * * /home/ada/scripts/rapor.sh &gt;&gt; /home/ada/logs/rapor.log 2&gt;&amp;1
</code></pre>

<p>Buradaki <code class="language-plaintext highlighter-rouge">2&gt;&amp;1</code>, standart hata akışını standart çıktıyla aynı log dosyasına gönderir. Böylece cron’un sessizliğini bozup gerçek hatayı yakalayabilirsiniz. Ancak <code class="language-plaintext highlighter-rouge">SHELL=/bin/bash</code> yazmak Bash’i otomatik olarak login veya interaktif shell yapmaz; <code class="language-plaintext highlighter-rouge">.bashrc</code> dosyasının okunacağı anlamına gelmez.</p>

<p>Script içinde kritik komutlar için mutlak yollar kullanmak daha da sağlamdır:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/usr/bin/env bash</span>
<span class="nb">set</span> <span class="nt">-euo</span> pipefail

<span class="nv">DATE</span><span class="o">=</span>/usr/bin/date
<span class="nv">PG_DUMP</span><span class="o">=</span>/usr/bin/pg_dump
<span class="nv">GZIP</span><span class="o">=</span>/usr/bin/gzip

<span class="nv">backup</span><span class="o">=</span><span class="s2">"/var/backups/app-</span><span class="si">$(</span><span class="nv">$DATE</span> +%F<span class="si">)</span><span class="s2">.sql.gz"</span>
<span class="nv">$PG_DUMP</span> appdb <span class="se">\v</span>ert  <span class="nv">$GZIP</span> <span class="o">&gt;</span> <span class="s2">"</span><span class="nv">$backup</span><span class="s2">"</span>
</code></pre></div></div>

<p>Bu script, hangi programların çalışacağını belirsiz <code class="language-plaintext highlighter-rouge">PATH</code> aramasına bırakmaz. <code class="language-plaintext highlighter-rouge">set -euo pipefail</code> ise başarısız komutları, tanımsız değişkenleri ve boru hattı hatalarını görünür kılar.</p>

<h2 id="göreli-yolların-gizli-tehlikesi">Göreli yolların gizli tehlikesi</h2>

<p>Script’in <code class="language-plaintext highlighter-rouge">./config.json</code> dosyasını okuması, cron’un doğru dizinde başladığını garanti etmez. Önce script dizinine geçmek güvenlidir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/usr/bin/env bash</span>
<span class="nb">set</span> <span class="nt">-euo</span> pipefail

<span class="nv">SCRIPT_DIR</span><span class="o">=</span><span class="s2">"</span><span class="si">$(</span><span class="nb">cd</span> <span class="nt">--</span> <span class="s2">"</span><span class="si">$(</span><span class="nb">dirname</span> <span class="nt">--</span> <span class="s2">"</span><span class="k">${</span><span class="nv">BASH_SOURCE</span><span class="p">[0]</span><span class="k">}</span><span class="s2">"</span><span class="si">)</span><span class="s2">"</span> <span class="o">&amp;&amp;</span> <span class="nb">pwd</span><span class="si">)</span><span class="s2">"</span>
<span class="nb">cd</span> <span class="s2">"</span><span class="nv">$SCRIPT_DIR</span><span class="s2">"</span>

/usr/bin/python3 generate_report.py <span class="nt">--config</span> ./config.json
</code></pre></div></div>

<p>Böylece script nereden çağrılırsa çağrılsın dosya yolları tutarlı kalır.</p>

<h2 id="ortamı-karşılaştırarak-hata-ayıklama">Ortamı karşılaştırarak hata ayıklama</h2>

<p>Cron’un gördüğü ortamı dosyaya yazdırabilirsiniz:</p>

<pre><code class="language-cron">* * * * * /usr/bin/env | /usr/bin/sort &gt; /tmp/cron-env.txt 2&gt;&amp;1
</code></pre>

<p>Terminalde de <code class="language-plaintext highlighter-rouge">env | sort &gt; /tmp/shell-env.txt</code> çalıştırıp iki dosyayı <code class="language-plaintext highlighter-rouge">diff</code> ile karşılaştırın. Ayrıca <code class="language-plaintext highlighter-rouge">command -v python3</code>, <code class="language-plaintext highlighter-rouge">command -v node</code> gibi komutlarla gerçek çalıştırılabilir yolları bulun.</p>

<p><code class="language-plaintext highlighter-rouge">.bashrc</code> dosyasını zorla yüklemek kısa vadede işe yarayabilir, fakat interaktif terminale özel komutlar cron altında yeni sorunlar çıkarabilir. En iyi yaklaşım; bağımlılıkları, yolları, çalışma dizinini ve loglamayı açıkça tanımlayan, kendi ortamını bilen bağımsız script’ler yazmaktır. Cron sürpriz yapmaz; yalnızca bizim terminalde fark etmeden taşıdığımız görünmez bagajı yanında getirmez.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="cron" /><category term="shell" /><category term="linux" /><category term="path" /><category term="bash" /><category term="hata ayıklama" /><summary type="html"><![CDATA[Terminalde kusursuz çalışan bir script’in cron tarafından başlatıldığında hata vermesi, Linux dünyasının klasik “ama benim makinemde çalışıyordu” vakalarındandır. Suç çoğu zaman cron’da değil; interaktif shell ile cron job’ının farklı PATH, çalışma dizini ve ortam değişkenleri kullanmasındadır.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/cron-calisiyor-ama-55.png" /><media:content medium="image" url="https://program.sonsuz.us/img/cron-calisiyor-ama-55.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C++’ta Const Borcu: İhmal Edilen const Doğruluğu Arayüzleri Nasıl Yaşlandırır?</title><link href="https://program.sonsuz.us/posts/cta-const-borcu-ihmal-edilen-const-dogrulugu-arayuzleri-nasil-yaslandirir/" rel="alternate" type="text/html" title="C++’ta Const Borcu: İhmal Edilen const Doğruluğu Arayüzleri Nasıl Yaşlandırır?" /><published>2026-10-19T00:00:00+00:00</published><updated>2026-10-19T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/cta-const-borcu-ihmal-edilen-const-dogrulugu-arayuzleri-nasil-yaslandirir</id><content type="html" xml:base="https://program.sonsuz.us/posts/cta-const-borcu-ihmal-edilen-const-dogrulugu-arayuzleri-nasil-yaslandirir/"><![CDATA[<p>C++’ta <code class="language-plaintext highlighter-rouge">const</code>, yalnızca derleyiciyi memnun eden küçük bir anahtar kelime değildir; bir arayüzün hangi işlemleri garanti ettiğini anlatan sözleşmedir. Bugün atlanan bir <code class="language-plaintext highlighter-rouge">const</code>, kodu hemen bozmayabilir. Ancak proje büyüdükçe yeniden kullanım, eşzamanlılık ve geriye dönük uyumluluk gibi alanlarda faiz işleyen bir tasarım borcuna dönüşür.
``</p>
<h2 id="const-doğruluğu-gerçekte-ne-söyler">Const doğruluğu gerçekte ne söyler?</h2>

<p>Bir nesneye <code class="language-plaintext highlighter-rouge">const</code> erişim, gözlemlenebilir durumunun değiştirilmeyeceği sözünü verir. Üye fonksiyonun sonundaki <code class="language-plaintext highlighter-rouge">const</code> ise bu sözün fonksiyon arayüzündeki karşılığıdır:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">User</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">name</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span>
        <span class="k">return</span> <span class="n">name_</span><span class="p">;</span>
    <span class="p">}</span>

<span class="k">private</span><span class="o">:</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name_</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Burada ilk <code class="language-plaintext highlighter-rouge">const</code>, döndürülen referans üzerinden metnin değiştirilemeyeceğini; ikinci <code class="language-plaintext highlighter-rouge">const</code> ise <code class="language-plaintext highlighter-rouge">name()</code> çağrısının <code class="language-plaintext highlighter-rouge">User</code> nesnesini değiştirmediğini belirtir. İki kullanım farklı soruları yanıtlar: “Sonuç değiştirilebilir mi?” ve “İşlem nesneyi değiştiriyor mu?”</p>

<p>Bunu kabaca bir durum geçişiyle ifade edebiliriz. Salt okunur işlem için beklenen ilişki:</p>

\[f(S) = (R, S)\]

<p>Burada $S$ nesnenin başlangıç durumu, $R$ sonuçtur. Değiştirici bir işlemdeyse yeni durum $S’$ oluşabilir:</p>

\[g(S) = (R, S'), \quad S' \neq S\]

<p><code class="language-plaintext highlighter-rouge">const</code>, ilk davranışı tür sistemi seviyesinde ilan eder ve derleyicinin bu sözleşmeyi denetlemesini sağlar.</p>

<h2 id="küçük-ihmal-büyük-arayüz-problemi">Küçük ihmal, büyük arayüz problemi</h2>

<p>Aşağıdaki fonksiyon nesneyi değiştirmese bile <code class="language-plaintext highlighter-rouge">const</code> olarak işaretlenmemiştir:</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="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">summary</span><span class="p">()</span> <span class="p">{</span> <span class="c1">// Aslında değişiklik yapmıyor</span>
        <span class="k">return</span> <span class="n">title_</span> <span class="o">+</span> <span class="s">": "</span> <span class="o">+</span> <span class="n">body_</span><span class="p">;</span>
    <span class="p">}</span>

<span class="k">private</span><span class="o">:</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">title_</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">body_</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Bu eksiklik yüzünden <code class="language-plaintext highlighter-rouge">const Report&amp;</code> alan kodlar <code class="language-plaintext highlighter-rouge">summary()</code> metodunu çağıramaz. Sorunu geçici olarak aşmak isteyen geliştiriciler nesneleri gereksiz yere kopyalayabilir, parametrelerden <code class="language-plaintext highlighter-rouge">const</code> niteliğini kaldırabilir veya daha kötüsü <code class="language-plaintext highlighter-rouge">const_cast</code> kullanabilir. Böylece yerel bir ihmal, çağrı zinciri boyunca yayılır.</p>

<table>
  <thead>
    <tr>
      <th>Tasarım tercihi</th>
      <th>Kısa vadeli sonuç</th>
      <th>Uzun vadeli etki</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Doğru <code class="language-plaintext highlighter-rouge">const</code> kullanımı</td>
      <td>Biraz daha dikkat gerektirir</td>
      <td>Açık sözleşme ve geniş kullanım alanı</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">const</code> kullanımını ertelemek</td>
      <td>Kod hızlı yazılır</td>
      <td>API esnekliği azalır</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">const_cast</code> ile aşmak</td>
      <td>Derleme hatası susturulur</td>
      <td>Tanımsız davranış ve bakım riski</td>
    </tr>
    <tr>
      <td>Her şeyi değiştirilebilir bırakmak</td>
      <td>Basit görünür</td>
      <td>Eşzamanlılık analizi zorlaşır</td>
    </tr>
  </tbody>
</table>

<h2 id="sonradan-eklemek-neden-pahalıdır">Sonradan eklemek neden pahalıdır?</h2>

<p>Bir metoda sonradan <code class="language-plaintext highlighter-rouge">const</code> eklemek kaynak kod düzeyinde küçük görünür:</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">string</span> <span class="n">summary</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
</code></pre></div></div>

<p>Fakat gerçek projede bu değişiklik; çağrılan yardımcı metotların, kullanılan işaretçilerin ve önbelleklerin de incelenmesini gerektirir. Ayrıca üye fonksiyonun <code class="language-plaintext highlighter-rouge">const</code> niteliği türünün parçasıdır. Sanal fonksiyonlarda taban ve türetilmiş sınıfların imzaları eşleşmelidir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">struct</span> <span class="nc">Document</span> <span class="p">{</span>
    <span class="k">virtual</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">title</span><span class="p">()</span> <span class="k">const</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">struct</span> <span class="nc">Invoice</span> <span class="o">:</span> <span class="n">Document</span> <span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">title</span><span class="p">()</span> <span class="k">const</span> <span class="k">override</span> <span class="p">{</span>
        <span class="k">return</span> <span class="s">"Fatura"</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Taban sınıfa sonradan <code class="language-plaintext highlighter-rouge">const</code> eklemek, bütün türetilmiş sınıfları değiştirebilir. Paylaşılan kütüphanelerde bu durum kaynak ve ikili uyumluluk planlarını da etkiler.</p>

<h2 id="mantıksal-const-ve-önbellekleme">Mantıksal const ve önbellekleme</h2>

<p>Bazen bir sorgu sonucu önbelleğe alınır. Kullanıcının gözünde nesne değişmezken içeride teknik bir güncelleme gerekir. Bunun için <code class="language-plaintext highlighter-rouge">mutable</code> bilinçli biçimde kullanılabilir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Calculator</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="kt">int</span> <span class="n">result</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">cached_</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">cache_</span> <span class="o">=</span> <span class="n">expensiveCalculation</span><span class="p">();</span>
            <span class="n">cached_</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">cache_</span><span class="p">;</span>
    <span class="p">}</span>

<span class="k">private</span><span class="o">:</span>
    <span class="kt">int</span> <span class="n">expensiveCalculation</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="mi">42</span><span class="p">;</span> <span class="p">}</span>
    <span class="k">mutable</span> <span class="kt">bool</span> <span class="n">cached_</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
    <span class="k">mutable</span> <span class="kt">int</span> <span class="n">cache_</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<p>Bu yaklaşım fiziksel değil, mantıksal değişmezliği temsil eder. Yine de <code class="language-plaintext highlighter-rouge">mutable</code>, eşzamanlı erişimi otomatik olarak güvenli yapmaz; gerekirse kilit veya atomik tür kullanılmalıdır.</p>

<h2 id="sağlam-arayüz-için-pratik-ölçüt">Sağlam arayüz için pratik ölçüt</h2>

<p>Bir metot tasarlarken önce “Bu işlem nesnenin kullanıcı tarafından gözlemlenen anlamını değiştiriyor mu?” diye sorun. Yanıt hayırsa metodu <code class="language-plaintext highlighter-rouge">const</code> yapın. Parametrelerde mümkün olduğunda <code class="language-plaintext highlighter-rouge">const T&amp;</code>, sahiplik aktarılmıyorsa salt okunur işaretçi veya görünüm türleri kullanın. <code class="language-plaintext highlighter-rouge">const</code> doğruluğunu baştan kurmak birkaç saniye; yıllar sonra bütün API ağında düzeltmek ise pahalı bir mimari operasyondur. Kısacası <code class="language-plaintext highlighter-rouge">const</code>, kısıtlama değil, gelecekteki kullanım biçimlerine açılan güvenli bir kapıdır.</p>

<p><img src="/img/cta-const-borcu-47.svg" alt="cta-const-borcu-47" /></p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c++" /><category term="const-correctness" /><category term="api-tasarımı" /><category term="yazılım-mimarisi" /><category term="teknik-borç" /><summary type="html"><![CDATA[C++’ta const, yalnızca derleyiciyi memnun eden küçük bir anahtar kelime değildir; bir arayüzün hangi işlemleri garanti ettiğini anlatan sözleşmedir. Bugün atlanan bir const, kodu hemen bozmayabilir. Ancak proje büyüdükçe yeniden kullanım, eşzamanlılık ve geriye dönük uyumluluk gibi alanlarda faiz işleyen bir tasarım borcuna dönüşür.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/cta-const-borcu-47.png" /><media:content medium="image" url="https://program.sonsuz.us/img/cta-const-borcu-47.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C++’ta const Referanslar ve Geçici Nesne Ömrü: Sessiz Tuzaklar</title><link href="https://program.sonsuz.us/posts/cta-const-referanslar-ve-gecici-nesne-omru-sessiz-tuzaklar/" rel="alternate" type="text/html" title="C++’ta const Referanslar ve Geçici Nesne Ömrü: Sessiz Tuzaklar" /><published>2026-10-19T00:00:00+00:00</published><updated>2026-10-19T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/cta-const-referanslar-ve-gecici-nesne-omru-sessiz-tuzaklar</id><content type="html" xml:base="https://program.sonsuz.us/posts/cta-const-referanslar-ve-gecici-nesne-omru-sessiz-tuzaklar/"><![CDATA[<p><img src="/img/cta-const-referanslar-21.svg" alt="cta-const-referanslar-21" /></p>

<p>C++’ta <code class="language-plaintext highlighter-rouge">const T&amp;</code> gördüğümüzde genellikle “güvenli, değiştirilemez referans” diye düşünürüz. Ancak geçici nesneler devreye girdiğinde konu yalnızca değiştirilebilirlikten ibaret değildir. Referansın neye, nerede ve nasıl bağlandığı; geçici nesnenin hemen yok edilmesini de kapsam sonuna kadar yaşamasını da sağlayabilir. Kısacası <code class="language-plaintext highlighter-rouge">const</code>, bazen nesneye adeta fazladan can verir.</p>

<p>``</p>

<h2 id="geçici-nesne-nedir">Geçici nesne nedir?</h2>

<p>Bir ifadenin sonucunu taşımak için oluşturulan, genellikle adı olmayan nesneye geçici nesne denir. Örneğin <code class="language-plaintext highlighter-rouge">std::string("merhaba")</code> bir geçici nesne üretir. Normal koşullarda bu nesne, içinde oluşturulduğu <strong>tam ifadenin</strong> sonunda yok edilir. Çoğu zaman bu nokta noktalı virgüldür.</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">string</span><span class="p">(</span><span class="s">"merhaba"</span><span class="p">);</span> <span class="c1">// Nesne bu satırın sonunda yok edilir.</span>
</code></pre></div></div>

<p>Basitleştirilmiş biçimde geçici nesnenin olağan ömrünü şöyle düşünebiliriz:</p>

\[L_{geçici} = t_{ifade\ sonu} - t_{oluşturma}\]

<p>Fakat uygun bir yerel referansa doğrudan bağlama yapılırsa ömür, referansın kapsamına kadar uzatılabilir:</p>

\[L_{uzatılmış} = t_{kapsam\ sonu} - t_{oluşturma}\]

<h2 id="const-referans-neden-özel"><code class="language-plaintext highlighter-rouge">const</code> referans neden özel?</h2>

<p>Lvalue referansları normalde geçici nesnelere bağlanamaz:</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">string</span><span class="o">&amp;</span> <span class="n">a</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">(</span><span class="s">"C++"</span><span class="p">);</span> <span class="c1">// Hata</span>
</code></pre></div></div>

<p>Bunun nedeni, kısa ömürlü ve isimsiz bir değerin değiştirilebilir bir lvalue referansı üzerinden kullanılmasının riskli kabul edilmesidir. Buna karşılık <code class="language-plaintext highlighter-rouge">const</code> lvalue referansı bağlanabilir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">a</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">(</span><span class="s">"C++"</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">a</span><span class="p">;</span> <span class="c1">// Güvenli: geçicinin ömrü a'nın kapsamına uzatıldı.</span>
</code></pre></div></div>

<table>
  <thead>
    <tr>
      <th>Bağlama biçimi</th>
      <th style="text-align: right">Geçiciye bağlanır mı?</th>
      <th style="text-align: right">Ömür uzar mı?</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">T&amp;</code></td>
      <td style="text-align: right">Hayır</td>
      <td style="text-align: right">Hayır</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">const T&amp;</code></td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">Genellikle evet</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">T&amp;&amp;</code></td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">Yerel değişkense evet</td>
    </tr>
    <tr>
      <td>Fonksiyon parametresi <code class="language-plaintext highlighter-rouge">const T&amp;</code></td>
      <td style="text-align: right">Evet</td>
      <td style="text-align: right">Yalnızca çağrının tam ifadesinin sonuna kadar</td>
    </tr>
  </tbody>
</table>

<p>Son satır kritik bir ayrıntıdır. Bir fonksiyon parametresine bağlanan geçici, fonksiyon çağrısı bittikten sonra saklanamaz.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">*</span> <span class="n">adres</span><span class="p">;</span>

<span class="kt">void</span> <span class="nf">sakla</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">metin</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">adres</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">metin</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">sakla</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">(</span><span class="s">"kaybolacak"</span><span class="p">));</span>
<span class="c1">// Bu noktadan sonra adres dangling pointer!</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">metin</code>, fonksiyon içinde geçerlidir; fakat çağrının bulunduğu tam ifade sona erince geçici nesne yok edilir.</p>

<h2 id="referansı-döndürmek-ömrü-uzatmaz">Referansı döndürmek ömrü uzatmaz</h2>

<p>En tehlikeli sürprizlerden biri, fonksiyondan <code class="language-plaintext highlighter-rouge">const</code> referans döndürmektir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="err">ü</span><span class="n">ret</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">(</span><span class="s">"geçici"</span><span class="p">);</span> <span class="c1">// Hatalı: yok edilecek nesneye referans</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">const</code> burada koruyucu kalkan değildir. Fonksiyon sona erdiğinde geçici nesne yok edilir ve dönen referans boşa çıkar. Doğru yaklaşım değeri döndürmektir:</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">string</span> <span class="err">ü</span><span class="n">ret</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">(</span><span class="s">"güvenli"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Modern C++, kopya eleme ve taşıma sayesinde bu kodu çoğunlukla ek maliyet oluşturmadan çalıştırır.</p>

<h2 id="i̇kinci-referans-ikinci-bir-ömür-vermez">İkinci referans ikinci bir ömür vermez</h2>

<p>Ömür uzatma aktarılabilir bir özellik değildir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">ilk</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">(</span><span class="s">"örnek"</span><span class="p">);</span>
<span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">ikinci</span> <span class="o">=</span> <span class="n">ilk</span><span class="p">;</span>
</code></pre></div></div>

<p>Nesnenin ömrü <code class="language-plaintext highlighter-rouge">ilk</code> nedeniyle uzatılmıştır. <code class="language-plaintext highlighter-rouge">ikinci</code>, aynı nesneye başka bir takma ad verir; ömrü yeniden başlatmaz veya kendi kapsamına göre genişletmez. Eğer <code class="language-plaintext highlighter-rouge">ikinci</code>, <code class="language-plaintext highlighter-rouge">ilk</code>ten daha uzun yaşarsa dangling referansa dönüşebilir.</p>

<h2 id="const-dönüş-değeri-her-zaman-yararlı-değildir"><code class="language-plaintext highlighter-rouge">const</code> dönüş değeri her zaman yararlı değildir</h2>

<p>Eski kodlarda <code class="language-plaintext highlighter-rouge">const T</code> döndüren fonksiyonlar görülebilir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">olu</span><span class="err">ş</span><span class="n">tur</span><span class="p">();</span>
</code></pre></div></div>

<p>Bu kullanım, modern C++’ta taşıma işlemlerini engelleyebilir; çünkü taşıma kurucuları çoğunlukla <code class="language-plaintext highlighter-rouge">T&amp;&amp;</code> bekler, <code class="language-plaintext highlighter-rouge">const T&amp;&amp;</code> değil. Değer döndüren fonksiyonlarda genellikle yalnızca <code class="language-plaintext highlighter-rouge">T</code> tercih edilmelidir.</p>

<p>Özet kural şudur: Yerel <code class="language-plaintext highlighter-rouge">const T&amp;</code> ve <code class="language-plaintext highlighter-rouge">T&amp;&amp;</code>, doğrudan bağlandıkları geçicinin ömrünü uzatabilir. Parametreler, döndürülen referanslar ve başka bir referans üzerinden yapılan bağlamalar için aynı güvenceyi varsaymayın. <code class="language-plaintext highlighter-rouge">const</code>, değişikliği sınırlar; her durumda ömür yönetmez.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c++" /><category term="const" /><category term="referanslar" /><category term="nesne-ömrü" /><category term="geçici-nesneler" /><category term="modern-c++" /><summary type="html"><![CDATA[C++’ta const T&amp; gördüğümüzde genellikle “güvenli, değiştirilemez referans” diye düşünürüz. Ancak geçici nesneler devreye girdiğinde konu yalnızca değiştirilebilirlikten ibaret değildir. Referansın neye, nerede ve nasıl bağlandığı; geçici nesnenin hemen yok edilmesini de kapsam sonuna kadar yaşamasını da sağlayabilir. Kısacası const, bazen nesneye adeta fazladan can verir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/cta-const-referanslar-21.png" /><media:content medium="image" url="https://program.sonsuz.us/img/cta-const-referanslar-21.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">C++’ta delete ve delete[] Farkı: Tek Bir Köşeli Parantezin Bedeli</title><link href="https://program.sonsuz.us/posts/cta-delete-ve-delete-farki-tek-bir-koseli-parantezin-bedeli/" rel="alternate" type="text/html" title="C++’ta delete ve delete[] Farkı: Tek Bir Köşeli Parantezin Bedeli" /><published>2026-10-19T00:00:00+00:00</published><updated>2026-10-19T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/cta-delete-ve-delete-farki-tek-bir-koseli-parantezin-bedeli</id><content type="html" xml:base="https://program.sonsuz.us/posts/cta-delete-ve-delete-farki-tek-bir-koseli-parantezin-bedeli/"><![CDATA[<p><img src="/img/cta-delete-ve-81.svg" alt="cta-delete-ve-81" /></p>

<p>C++’ta dinamik bellek yönetirken <code class="language-plaintext highlighter-rouge">delete</code> ile <code class="language-plaintext highlighter-rouge">delete[]</code> arasındaki iki köşeli parantez küçük görünebilir. Ancak yanlış silme ifadesini kullanmak; bellek sızıntısı, eksik yıkıcı çağrıları, heap bozulması ve yalnızca üretim ortamında ortaya çıkan gizemli çökmeler gibi ciddi sonuçlara yol açabilir.
``</p>
<h2 id="temel-eşleştirme-kuralı">Temel eşleştirme kuralı</h2>

<p>C++’ta bellek ayırma ve serbest bırakma işlemleri doğru biçimde eşleştirilmelidir:</p>

<table>
  <thead>
    <tr>
      <th>Bellek ayırma</th>
      <th>Belleği serbest bırakma</th>
      <th>Kullanım amacı</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">new T</code></td>
      <td><code class="language-plaintext highlighter-rouge">delete</code></td>
      <td>Tek bir nesne</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">new T[n]</code></td>
      <td><code class="language-plaintext highlighter-rouge">delete[]</code></td>
      <td>Nesne dizisi</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">malloc</code> / <code class="language-plaintext highlighter-rouge">calloc</code></td>
      <td><code class="language-plaintext highlighter-rouge">free</code></td>
      <td>C tarzı ham bellek</td>
    </tr>
  </tbody>
</table>

<p>Başka bir ifadeyle şu eşitlik korunmalıdır:</p>

\[new\ T \longleftrightarrow delete\]

\[new\ T[n] \longleftrightarrow delete[]\]

<p><code class="language-plaintext highlighter-rouge">new[]</code> ile oluşturulan bir diziyi normal <code class="language-plaintext highlighter-rouge">delete</code> ile silmek <strong>tanımsız davranıştır</strong>. Tanımsız davranış, programın mutlaka anında çökeceği anlamına gelmez. Program düzgün çalışıyor gibi görünebilir, rastgele sonuç üretebilir veya başka bir noktada çökebilir. Tehlikeli olan da budur.</p>

<h2 id="neden-iki-farklı-silme-işlemi-var">Neden iki farklı silme işlemi var?</h2>

<p>Tek bir nesne oluşturulduğunda çalışma zamanı yalnızca o nesnenin yıkıcısını çağırır ve belleği serbest bırakır. Dizilerde ise her elemanın ayrı ayrı yok edilmesi gerekir.</p>

<p>Bir dizi $n$ elemandan oluşuyorsa beklenen yıkıcı çağrısı sayısı şöyledir:</p>

\[D(n) = n\]

<p>Bazı C++ çalışma zamanı uygulamaları, ayrılan bloğun başında eleman sayısını saklayan ve halk arasında <strong>array cookie</strong> denilen ek bilgiler tutar. <code class="language-plaintext highlighter-rouge">delete[]</code>, bu bilgiyi kullanarak kaç yıkıcı çağrılması gerektiğini belirleyebilir. Standart, bu mekanizmanın nasıl uygulanacağını zorunlu kılmaz; fakat programcıya doğru silme ifadesini kullanma sorumluluğunu verir.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Sensor</span> <span class="p">{</span>
<span class="nl">public:</span>
    <span class="n">Sensor</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>

    <span class="o">~</span><span class="n">Sensor</span><span class="p">()</span> <span class="p">{</span>
        <span class="c1">// Dosya, soket veya başka bir kaynak burada kapatılabilir.</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="p">{</span>
    <span class="n">Sensor</span><span class="o">*</span> <span class="n">sensors</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Sensor</span><span class="p">[</span><span class="mi">4</span><span class="p">];</span>

    <span class="c1">// Dört elemanın da yıkıcısını çalıştırır.</span>
    <span class="k">delete</span><span class="p">[]</span> <span class="n">sensors</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Burada <code class="language-plaintext highlighter-rouge">delete sensors;</code> kullanılsaydı sonuç tanımsız olurdu. Yalnızca ilk elemanın yıkıcısının çağrılacağını varsaymak bile güvenli değildir; standart böyle bir garanti sunmaz.</p>

<h2 id="i̇lkel-türlerde-sorun-yok-mu">İlkel türlerde sorun yok mu?</h2>

<p><code class="language-plaintext highlighter-rouge">int</code> veya <code class="language-plaintext highlighter-rouge">double</code> gibi türlerin yıkıcısı olmadığı için yanlış kullanımın zararsız olduğu düşünülebilir:</p>

<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">scores</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">[</span><span class="mi">100</span><span class="p">];</span>
<span class="k">delete</span> <span class="n">scores</span><span class="p">;</span> <span class="c1">// Hatalı: delete[] kullanılmalıydı.</span>
</code></pre></div></div>

<p>Bu kod yine tanımsız davranıştır. Bellek yöneticisi dizi tahsisini farklı biçimde izleyebilir. Hata hemen görünmese bile heap yapısı bozulabilir. Doğru kullanım şöyledir:</p>

<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">scores</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">[</span><span class="mi">100</span><span class="p">];</span>
<span class="k">delete</span><span class="p">[]</span> <span class="n">scores</span><span class="p">;</span>
<span class="n">scores</span> <span class="o">=</span> <span class="nb">nullptr</span><span class="p">;</span>
</code></pre></div></div>

<p>İşaretçiyi <code class="language-plaintext highlighter-rouge">nullptr</code> yapmak, aynı işaretçinin yanlışlıkla tekrar silinmesi riskini azaltabilir. Ayrıca <code class="language-plaintext highlighter-rouge">delete nullptr</code> ve <code class="language-plaintext highlighter-rouge">delete[] nullptr</code> güvenlidir; ikisi de işlem yapmaz.</p>

<h2 id="hataları-nasıl-yakalarız">Hataları nasıl yakalarız?</h2>

<p>AddressSanitizer, Valgrind ve benzeri araçlar tahsis-silme uyumsuzluklarını bulabilir. GCC veya Clang ile örnek bir kontrol derlemesi şöyledir:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>g++ <span class="nt">-std</span><span class="o">=</span>c++20 <span class="nt">-Wall</span> <span class="nt">-Wextra</span> <span class="nt">-fsanitize</span><span class="o">=</span>address main.cpp
./a.out
</code></pre></div></div>

<p>Derleyici uyarıları yardımcı olsa da işaretçi farklı fonksiyonlara taşındığında hatayı her zaman yakalayamaz.</p>

<h2 id="modern-c-çözümü">Modern C++ çözümü</h2>

<p>En güvenli yaklaşım, çıplak <code class="language-plaintext highlighter-rouge">new[]</code> kullanmaktan kaçınmaktır. Boyutu çalışma zamanında belirlenen diziler için <code class="language-plaintext highlighter-rouge">std::vector</code>, sabit boyutlular için <code class="language-plaintext highlighter-rouge">std::array</code> tercih edilmelidir:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;vector&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">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">scores</span><span class="p">(</span><span class="mi">100</span><span class="p">);</span>
    <span class="n">scores</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">42</span><span class="p">;</span>
<span class="p">}</span> <span class="c1">// Bellek otomatik olarak temizlenir.</span>
</code></pre></div></div>

<p>Dinamik bir diziye gerçekten ihtiyaç varsa <code class="language-plaintext highlighter-rouge">std::unique_ptr&lt;T[]&gt;</code> kullanılabilir. Böylece doğru <code class="language-plaintext highlighter-rouge">delete[]</code> otomatik olarak çağrılır. Kısacası, <code class="language-plaintext highlighter-rouge">new</code> gördüğünüzde <code class="language-plaintext highlighter-rouge">delete</code>, <code class="language-plaintext highlighter-rouge">new[]</code> gördüğünüzde <code class="language-plaintext highlighter-rouge">delete[]</code> düşünün; daha iyisi, bu işi RAII kapsayıcılarına bırakın.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="c++" /><category term="bellek yönetimi" /><category term="delete" /><category term="delete[]" /><category term="tanımsız davranış" /><category term="modern c++" /><summary type="html"><![CDATA[C++’ta dinamik bellek yönetirken delete ile delete[] arasındaki iki köşeli parantez küçük görünebilir. Ancak yanlış silme ifadesini kullanmak; bellek sızıntısı, eksik yıkıcı çağrıları, heap bozulması ve yalnızca üretim ortamında ortaya çıkan gizemli çökmeler gibi ciddi sonuçlara yol açabilir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/cta-delete-ve-81.png" /><media:content medium="image" url="https://program.sonsuz.us/img/cta-delete-ve-81.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Diferansiyel Sürüşlü Robotlar Tekerlek Hızı Farkıyla Nasıl Döner?</title><link href="https://program.sonsuz.us/posts/diferansiyel-suruslu-robotlar-tekerlek-hizi-farkiyla-nasil-doner/" rel="alternate" type="text/html" title="Diferansiyel Sürüşlü Robotlar Tekerlek Hızı Farkıyla Nasıl Döner?" /><published>2026-10-19T00:00:00+00:00</published><updated>2026-10-19T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/diferansiyel-suruslu-robotlar-tekerlek-hizi-farkiyla-nasil-doner</id><content type="html" xml:base="https://program.sonsuz.us/posts/diferansiyel-suruslu-robotlar-tekerlek-hizi-farkiyla-nasil-doner/"><![CDATA[<p>Diferansiyel sürüşlü bir robotun direksiyonu yoktur; buna rağmen kıvrak biçimde dönebilir, hatta olduğu yerde kendi ekseni etrafında dans edebilir. Bu yeteneğin sırrı, sağ ve sol tekerleklerin farklı hızlarda döndürülmesidir. Alışveriş arabasını tek taraftan daha güçlü ittiğinizi düşünün: hız farkı, aracın yönünü değiştirir.</p>

<p><img src="/img/diferansiyel-suruslu-robotlar-65.svg" alt="diferansiyel-suruslu-robotlar-65" /></p>

<p>``</p>
<h2 id="temel-mekanik-düzen">Temel mekanik düzen</h2>

<p>Bu robotlarda aynı eksen üzerinde bulunan iki bağımsız tahrik tekerleği vardır. Tekerlekler arasındaki mesafeye <strong>iz genişliği</strong> veya dingil uzunluğu denir ve genellikle $L$ ile gösterilir. Sol tekerleğin doğrusal hızı $v_l$, sağ tekerleğinki ise $v_r$ olsun.</p>

<p>Robotun merkezinin ileri yönlü doğrusal hızı iki tekerlek hızının ortalamasıdır:</p>

\[v = (v_r + v_l) / 2\]

<p>Açısal hız ise tekerlekler arasındaki hız farkıyla belirlenir:</p>

\[ω = (v_r - v_l) / L\]

<p>Bu ikinci denklem robotun dönüş mantığını özetler. Hız farkı büyüdükçe robot daha hızlı döner. Tekerlekler arası mesafe büyüdükçe aynı hız farkıyla elde edilen açısal hız azalır; çünkü geniş bir robotu çevirmek daha zordur.</p>

<table>
  <thead>
    <tr>
      <th>Sol ve sağ hız ilişkisi</th>
      <th>Robotun davranışı</th>
      <th style="text-align: right">Açısal hız</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>$v_l = v_r &gt; 0$</td>
      <td>Düz ileri gider</td>
      <td style="text-align: right">$0$</td>
    </tr>
    <tr>
      <td>$v_l &lt; v_r$</td>
      <td>Sola döner</td>
      <td style="text-align: right">Pozitif</td>
    </tr>
    <tr>
      <td>$v_l &gt; v_r$</td>
      <td>Sağa döner</td>
      <td style="text-align: right">Negatif</td>
    </tr>
    <tr>
      <td>$v_l = -v_r$</td>
      <td>Olduğu yerde döner</td>
      <td style="text-align: right">En yüksek</td>
    </tr>
    <tr>
      <td>$v_l = v_r = 0$</td>
      <td>Durur</td>
      <td style="text-align: right">$0$</td>
    </tr>
  </tbody>
</table>

<p>Buradaki sağ ve sol yön işaretleri, kullanılan koordinat sistemine göre ters tanımlanabilir. Önemli olan yazılımın ve matematiksel modelin aynı işaret kuralını kullanmasıdır.</p>

<h2 id="görünmez-dönüş-merkezi-icc">Görünmez dönüş merkezi: ICC</h2>

<p>Robot viraj alırken iki tekerlek aynı merkez çevresinde fakat farklı yarıçaplarda yay çizer. Bu ortak noktaya <strong>Anlık Dönüş Merkezi</strong> ya da ICC denir. İç taraftaki tekerlek daha kısa, dış taraftaki tekerlek daha uzun yol aldığı için dış tekerlek daha hızlı dönmelidir.</p>

<p>Robot merkezinin dönüş yarıçapı $R$, açısal hız sıfır değilken şöyle bulunabilir:</p>

\[R = v / ω = L(v_r + v_l) / (2(v_r - v_l))\]

<p>Tekerlek hızları birbirine yaklaştığında paydadaki fark küçülür ve $R$ büyür; robot geniş bir yay çizer. Hızlar eşit olduğunda yarıçap teorik olarak sonsuza gider, yani hareket düz bir çizgiye dönüşür. Hızlar eşit büyüklükte ve zıt yönlü olduğundaysa $v=0$ olur; dönüş merkezi robotun tam ortasına gelir.</p>

<h2 id="basit-bir-hız-hesabı">Basit bir hız hesabı</h2>

<p>Aşağıdaki Python fonksiyonu, tekerlek hızlarından robotun doğrusal ve açısal hızını hesaplar:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">robot_hizi</span><span class="p">(</span><span class="n">sol_hiz</span><span class="p">,</span> <span class="n">sag_hiz</span><span class="p">,</span> <span class="n">tekerlek_araligi</span><span class="p">):</span>
    <span class="n">dogrusal_hiz</span> <span class="o">=</span> <span class="p">(</span><span class="n">sag_hiz</span> <span class="o">+</span> <span class="n">sol_hiz</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span>
    <span class="n">acisal_hiz</span> <span class="o">=</span> <span class="p">(</span><span class="n">sag_hiz</span> <span class="o">-</span> <span class="n">sol_hiz</span><span class="p">)</span> <span class="o">/</span> <span class="n">tekerlek_araligi</span>
    <span class="k">return</span> <span class="n">dogrusal_hiz</span><span class="p">,</span> <span class="n">acisal_hiz</span>

<span class="n">v</span><span class="p">,</span> <span class="n">omega</span> <span class="o">=</span> <span class="nf">robot_hizi</span><span class="p">(</span><span class="mf">0.20</span><span class="p">,</span> <span class="mf">0.40</span><span class="p">,</span> <span class="mf">0.30</span><span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="n">omega</span><span class="p">)</span>
</code></pre></div></div>

<p>Bu örnekte robotun doğrusal hızı $0.30\ m/s$, açısal hızı yaklaşık $0.67\ rad/s$ olur. Sağ tekerlek daha hızlı olduğu için robot sola yönelir.</p>

<p>Motorlar genellikle doğrusal hız yerine açısal tekerlek hızıyla kontrol edilir. Tekerlek yarıçapı $r$ ve motor açısal hızı $ω_w$ ise doğrusal hız:</p>

\[v_w = rω_w\]

<p>bağıntısıyla bulunur. Böylece enkoderden ölçülen dönüş hızı, robot kinematiğinde kullanılabilir.</p>

<h2 id="gerçek-dünya-neden-formüllerden-daha-huysuzdur">Gerçek dünya neden formüllerden daha huysuzdur?</h2>

<p>Teorik model tekerleklerin kaymadığını varsayar. Gerçekte zemin sürtünmesi, motor farklılıkları, pil gerilimi ve ağırlık dağılımı dönüşü etkiler. Aynı PWM değeri iki motorda aynı hızı üretmeyebilir. Bu nedenle enkoder geri bildirimi ve PID kontrolü kullanılarak her tekerleğin hedef hızı ayrı ayrı korunur.</p>

<p>Kısacası diferansiyel sürüş, mekanik olarak sade fakat matematiksel olarak güçlüdür: ortalama hız robotu ilerletir, hız farkı ise döndürür. İki motorun uyumlu anlaşmazlığı, robotun tüm yön kabiliyetini oluşturur.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="robotik" /><category term="diferansiyel sürüş" /><category term="kinematik" /><category term="tekerlek hızı" /><category term="python" /><category term="mobil robotlar" /><summary type="html"><![CDATA[Diferansiyel sürüşlü bir robotun direksiyonu yoktur; buna rağmen kıvrak biçimde dönebilir, hatta olduğu yerde kendi ekseni etrafında dans edebilir. Bu yeteneğin sırrı, sağ ve sol tekerleklerin farklı hızlarda döndürülmesidir. Alışveriş arabasını tek taraftan daha güçlü ittiğinizi düşünün: hız farkı, aracın yönünü değiştirir.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/diferansiyel-suruslu-robotlar-65.png" /><media:content medium="image" url="https://program.sonsuz.us/img/diferansiyel-suruslu-robotlar-65.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Fırtınada Bile Gören Robotlar: Otonom Araçlarda Sensör Füzyonu</title><link href="https://program.sonsuz.us/posts/firtinada-bile-goren-robotlar-otonom-araclarda-sensor-fuzyonu/" rel="alternate" type="text/html" title="Fırtınada Bile Gören Robotlar: Otonom Araçlarda Sensör Füzyonu" /><published>2026-10-19T00:00:00+00:00</published><updated>2026-10-19T00:00:00+00:00</updated><id>https://program.sonsuz.us/posts/firtinada-bile-goren-robotlar-otonom-araclarda-sensor-fuzyonu</id><content type="html" xml:base="https://program.sonsuz.us/posts/firtinada-bile-goren-robotlar-otonom-araclarda-sensor-fuzyonu/"><![CDATA[<p>Güneşli bir günde yolu algılamak otonom araçlar için görece kolaydır. Ancak sis çöktüğünde, yağmur kamera görüntüsünü bozduğunda veya kar taneleri LiDAR ölçümlerinde hayalet noktalar oluşturduğunda işler değişir. Sensör füzyonu, farklı sensörlerin güçlü yanlarını birleştirerek aracın tek bir ölçüme körü körüne güvenmesini önler. Kısacası ekip çalışması yapar: Kamera renkleri söyler, radar mesafeyi ölçer, LiDAR çevrenin üç boyutlu haritasını çıkarır.</p>

<p><img src="/img/firtinada-bile-goren-83.svg" alt="firtinada-bile-goren-83" /></p>

<p>``</p>

<h2 id="tek-bir-sensör-neden-yetmez">Tek Bir Sensör Neden Yetmez?</h2>

<p>Her sensör çevreyi farklı bir fiziksel ilkeye göre gözlemler. Kameralar görünür ışığı, radar elektromanyetik dalgaların yansımasını, LiDAR ise lazer darbelerinin dönüş süresini kullanır. Bu çeşitlilik aynı zamanda hata çeşitliliği demektir. Kamera sisi yoğun bir duvar gibi görebilirken radar sisin içinden çalışmayı sürdürebilir. Buna karşılık radar, nesnenin bisiklet mi yoksa trafik levhası mı olduğunu kamera kadar başarılı sınıflandıramaz.</p>

<table>
  <thead>
    <tr>
      <th>Sensör</th>
      <th>Güçlü yönü</th>
      <th>Kötü havadaki sorunu</th>
      <th>Füzyondaki rolü</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Kamera</td>
      <td>Renk, şerit ve nesne sınıfı</td>
      <td>Sis, karanlık ve su damlaları</td>
      <td>Anlamsal bilgi sağlar</td>
    </tr>
    <tr>
      <td>LiDAR</td>
      <td>Hassas 3B geometri</td>
      <td>Yağmur ve karda sahte yansımalar</td>
      <td>Şekil ve konum üretir</td>
    </tr>
    <tr>
      <td>Radar</td>
      <td>Hız ve mesafe ölçümü</td>
      <td>Düşük açısal çözünürlük</td>
      <td>Zorlu havada kararlı ölçüm sağlar</td>
    </tr>
    <tr>
      <td>Ultrasonik</td>
      <td>Yakın mesafede ekonomiktir</td>
      <td>Rüzgâr ve yüzey yapısından etkilenir</td>
      <td>Park ve düşük hız desteği verir</td>
    </tr>
    <tr>
      <td>GNSS/IMU</td>
      <td>Araç konumu ve hareketi</td>
      <td>Tünel, yansıma ve sürüklenme</td>
      <td>Küresel ve göreli hareketi izler</td>
    </tr>
  </tbody>
</table>

<h2 id="güven-ağırlık-ve-olasılık">Güven, Ağırlık ve Olasılık</h2>

<p>Füzyonun temel fikri, bütün sensörlere eşit oy hakkı vermek değildir. Sistem, mevcut koşullara göre her ölçümün güvenilirliğini değerlendirir. Bir sensörün ölçümü $z_i$, güven ağırlığı $w_i$ ise basit bir birleşik tahmin şöyle yazılabilir:</p>

\[x = (w_1z_1 + w_2z_2 + ... + w_nz_n) / (w_1 + w_2 + ... + w_n)\]

<p>Yoğun siste kameranın $w$ değeri azaltılırken radarın ağırlığı artırılabilir. Daha gelişmiş sistemlerde Kalman filtresi, genişletilmiş Kalman filtresi, parçacık filtresi veya Bayesçi çıkarım kullanılır. Bayes yaklaşımı, yeni bir ölçüm geldiğinde önceki inancı günceller:</p>

\[P(x\vert z) = P(z\vert x)P(x) / P(z)\]

<p>Burada $P(x)$ önceki tahmini, $P(z\vert x)$ ölçümün bu tahmin altında görülme olasılığını, $P(x\vert z)$ ise güncellenmiş sonucu temsil eder. Böylece araç, “Radar önümde bir şey olduğunu söylüyor ama kamera emin değil” durumunu matematiksel olarak çözebilir.</p>

<h2 id="basit-bir-uyarlanabilir-füzyon-örneği">Basit Bir Uyarlanabilir Füzyon Örneği</h2>

<p>Aşağıdaki Python kodu, hava durumuna göre kamera ve radar ölçümlerinin ağırlıklarını değiştirir. Gerçek araçlarda belirsizlik kovaryans matrisleri ve zaman senkronizasyonu kullanılır; bu örnek temel mantığı görünür kılar.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">fuse_distance</span><span class="p">(</span><span class="n">camera</span><span class="p">,</span> <span class="n">radar</span><span class="p">,</span> <span class="n">weather</span><span class="p">):</span>
    <span class="c1"># Açık havada kamera daha güvenilirken siste radar öne çıkar.
</span>    <span class="n">weights</span> <span class="o">=</span> <span class="p">{</span>
        <span class="sh">"</span><span class="s">clear</span><span class="sh">"</span><span class="p">:</span> <span class="p">(</span><span class="mf">0.6</span><span class="p">,</span> <span class="mf">0.4</span><span class="p">),</span>
        <span class="sh">"</span><span class="s">rain</span><span class="sh">"</span><span class="p">:</span>  <span class="p">(</span><span class="mf">0.3</span><span class="p">,</span> <span class="mf">0.7</span><span class="p">),</span>
        <span class="sh">"</span><span class="s">fog</span><span class="sh">"</span><span class="p">:</span>   <span class="p">(</span><span class="mf">0.15</span><span class="p">,</span> <span class="mf">0.85</span><span class="p">)</span>
    <span class="p">}</span>

    <span class="n">camera_w</span><span class="p">,</span> <span class="n">radar_w</span> <span class="o">=</span> <span class="n">weights</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="n">weather</span><span class="p">,</span> <span class="p">(</span><span class="mf">0.5</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">))</span>
    <span class="k">return</span> <span class="n">camera</span> <span class="o">*</span> <span class="n">camera_w</span> <span class="o">+</span> <span class="n">radar</span> <span class="o">*</span> <span class="n">radar_w</span>

<span class="n">result</span> <span class="o">=</span> <span class="nf">fuse_distance</span><span class="p">(</span><span class="n">camera</span><span class="o">=</span><span class="mf">24.0</span><span class="p">,</span> <span class="n">radar</span><span class="o">=</span><span class="mf">21.5</span><span class="p">,</span> <span class="n">weather</span><span class="o">=</span><span class="sh">"</span><span class="s">fog</span><span class="sh">"</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="s">Tahmini mesafe: </span><span class="si">{</span><span class="n">result</span><span class="si">:</span><span class="p">.</span><span class="mi">2</span><span class="n">f</span><span class="si">}</span><span class="s"> metre</span><span class="sh">"</span><span class="p">)</span>
</code></pre></div></div>

<p>Burada sisli havada radar ölçümü sonuca daha fazla yön verir. Fakat yalnızca hava etiketi kullanmak yeterli değildir. Kamera kontrastı, LiDAR dönüş yoğunluğu, radar sinyal-gürültü oranı ve sensör sıcaklığı gibi anlık kalite göstergeleri de ağırlıkları dinamik biçimde değiştirmelidir.</p>

<h2 id="füzyonun-gizli-kahramanları">Füzyonun Gizli Kahramanları</h2>

<p>Başarılı bir sistem için sensörlerin kalibrasyonu ve zaman eşlemesi kritiktir. Milisaniyelik gecikme, hızlı hareket eden bir aracın farklı konumlarda algılanmasına yol açabilir. Ayrıca sensörler ortak koordinat sistemine dönüştürülmelidir. Aksi hâlde radarın “ön sağ” dediği nesne, kamera görüntüsünde yanlış piksele bağlanır.</p>

<p>Sonuç olarak sensör füzyonu kötü havayı ortadan kaldırmaz; belirsizliği yönetilebilir hâle getirir. Güvenilir otonomi, en parlak sensöre sahip olmak değil, hangi sensöre ne zaman güvenileceğini bilmektir. Robotik aracın süper gücü kusursuz görmek değil, şüphe etmeyi matematikle öğrenmektir.</p>]]></content><author><name>Sonsuz Us</name></author><category term="Bilgi" /><category term="robotik" /><category term="otonom araçlar" /><category term="sensör füzyonu" /><category term="lidar" /><category term="radar" /><category term="bilgisayarlı görü" /><category term="yapay zeka" /><summary type="html"><![CDATA[Güneşli bir günde yolu algılamak otonom araçlar için görece kolaydır. Ancak sis çöktüğünde, yağmur kamera görüntüsünü bozduğunda veya kar taneleri LiDAR ölçümlerinde hayalet noktalar oluşturduğunda işler değişir. Sensör füzyonu, farklı sensörlerin güçlü yanlarını birleştirerek aracın tek bir ölçüme körü körüne güvenmesini önler. Kısacası ekip çalışması yapar: Kamera renkleri söyler, radar mesafeyi ölçer, LiDAR çevrenin üç boyutlu haritasını çıkarır.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://program.sonsuz.us/img/firtinada-bile-goren-83.png" /><media:content medium="image" url="https://program.sonsuz.us/img/firtinada-bile-goren-83.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>