---
title: 'Derleme Aşamaları'
source: 'https://academia.sh/tr/kurslar/c-temelleri/derleme-asamalari'
course: 'C Temelleri'
language: tr
updated: '2026-09-13T05:07:32+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Dört aşamanın her birinin karar verirken hangi girdiye baktığını ayırt eder'
    - 'Küçük bir ölçüm kesitiyle dört sınıfı tek koşumda karşılaştırır'
    - 'Aşamaların sırayla çalıştığını ve geri dönüşü olmadığını bir kaynak örneğiyle gösterir'
---

# Derleme Aşamaları

Dört aşamanın her biri farklı bir girdiye bakar: ön işlemci yalnız metne, derleyici tek bir birime, bağlayıcı birden çok birime, koşum ise yalnız veriye. Küçük bir ölçüm kesitiyle dördü yan yana koşturuluyor; ayrı bir çift program da aynı kaynağın bir satırının, kaynakta önceden verilmiş bir kararla iki farklı derlemeye nasıl girdiğini gösteriyor.

Önceki ders dört aşamayı adlandırdı: ön işlemci, derleyici, bağlayıcı, koşum; üç dosyalık
çekirdeği tek koşumda çalıştırıp on dört gözlemi bu dört sınıfa dağıttı. Bu ders aynı dört
adı, her birinin karar verirken **hangi girdiye baktığı** sorusuyla derinleştiriyor.
Dört aşama aynı kaynağa bakar, ama hiçbiri aynı şeyi görmez — biri yalnız metin görür, biri
tek bir dosya, biri birden çok dosyanın kesişimi, biri de yalnız o an elindeki veri. Bu fark
soyut bir sınıflandırma değildir; her aşamanın elinde gerçekten o girdiden başka hiçbir şey
yoktur ve bu ders bunu ölçerek gösterecek.

## Dört Girdi

Her aşamanın kararını verirken elinde olan şey farklıdır:

| Sınıf | Baktığı girdi |
|---|---|
| ön işlemci | Yalnız kaynağın metni; tip, sabit, birim kavramlarının hiçbiri henüz yok |
| derleyici | Tek bir çeviri biriminin tamamı; o birimin dışına bakmaz |
| bağlayıcı | Birden çok birimin ürettiği tanımlar; içeriklerini yorumlamaz, yalnız adları eşler |
| koşum | Programın kendi verisi; kaynağın metni artık elde değildir |

Bu sıralama aynı zamanda bir daralma sırasıdır. Ön işlemcinin elindeki bilgi en genişidir —
bütün kaynak metnine erişebilir, ama içindeki hiçbir yapıyı anlamaz. Derleyici bu metnin
yalnız bir biriminden sorumludur, ama artık tip ve ifade gibi yapıları görür. Bağlayıcı tek
bir birimi bile görmez; yalnız birimlerin dışa açtığı adları görür. Koşum ise kaynağın hiçbir
parçasını görmez, yalnız programın o an elindeki veriyi görür.

Bu daralma tek yönlüdür: bir aşama, bir öncekinin kaybettiği bilgiyi geri kazanamaz. Bir
makro adı ön işlemcide metne dönüşür ve derleyici o adı hiç görmez — gördüğü yalnız yerine
konmuş metindir, "bu bir makroydu" bilgisi kaynakta iz bırakmaz. Aynı şekilde bir değişkenin
tipi derleyicide ikili bir düzene (nesne dosyasındaki bir sembole) indirgenir; bağlayıcı bu
sembolü yalnız adıyla eşler, o adın hangi tipten bir değişkene ait olduğunu bilmez ve
bilmesine gerek de yoktur — tip uyuşmazlığı varsa onu derleyici zaten kendi aşamasında
yakalamıştır. Her aşama, kendinden öncekinin işini bitirdiğini varsayarak çalışır.

Bu güven zinciri kaynağın kendisiyle sınırlı değildir. Bağlayıcı, girdisi olan nesne
dosyalarının doğru bir derleyiciden geldiğini de varsayar; herhangi bir aracın ürettiği,
aynı biçimi taşıyan bir nesne dosyası aynı şekilde kabul edilir. Bu, dört aşamanın
sırasının neden bir uygulamaya değil bir **biçime** bağlı olduğunu gösteriyor — her aşama
kendinden önceki adımın hangi araçla yürütüldüğünü değil, ürettiği biçimin sözleşmeye uyup
uymadığını denetler.

## Dört Sınıf, Dört Satır

Aşağıdaki kesit önceki dersin çekirdeğinden dört satır alıyor — her sınıftan bir tane — ve
yalnız bu dördünü yan yana koşturuyor. Bağlayıcı sınıfını göstermek için yine iki birim
gerekiyor.

```c
// asama.h — baska birimde tanimli tek adin bildirimi
#ifndef ASAMA_H
#define ASAMA_H

int kimlik(void);

#endif
```

`asama.h` kendi başına ne derlenir ne de bir birim sayılır — bir dosyayı bir birim yapan şey,
onun `cc` komutuna ayrı bir kaynak olarak verilmesidir, `#include` ile başka bir dosyanın
içine kopyalanması değil. Bu ders boyunca `asama.h` doğrulayıcıya yalnız KAYNAK olarak
görünecek: içeriği ancak onu `#include` eden birimin metnine karıştıktan sonra derleyicinin
önüne gelir. Başlık dosyasının bu paylaşım rolü sıradaki dersin konusu.

```c
// secim.c — ikinci birim: tanim burada, cagri baglamada cozulur
#include "asama.h"

int kimlik(void) {
    return 7;
}
```

```c
// asama.c — dort sinifi yan yana olcen kucuk kesit: her sinieftan tek satir
#include <stdio.h>
#include "asama.h"

#define KAT 3

static void gozle(const char *ad, const char *sinif, const char *kanit) {
    printf("%-30s%-14s%s\n", ad, sinif, kanit);
}

int main(void) {
    char tampon[64];

    printf("%-30s%-14s%s\n", "gozlem", "asama", "kanit");

    snprintf(tampon, sizeof tampon, "KAT metni %d olarak konuldu", KAT);
    gozle("makro degeri", "on islemci", tampon);

    int tam = 7 / 2;
    double kesirli = 7 / 2.0;
    snprintf(tampon, sizeof tampon, "tam %d kesirli %.1f", tam, kesirli);
    gozle("islecin tipe gore secimi", "derleyici", tampon);

    snprintf(tampon, sizeof tampon, "cagri %d verdi", kimlik());
    gozle("baska birimdeki islev", "baglayici", tampon);

    int veri[] = {4, 8, 15, 16};
    int toplam = 0;
    for (size_t i = 0; i < sizeof veri / sizeof veri[0]; i++) {
        toplam += veri[i];
    }
    const char *karar = (toplam > 40) ? "buyuk" : "kucuk";
    gozle("veriye bagli dallanma", "kosum", karar);

    return 0;
}
```

```
gozlem                        asama         kanit
makro degeri                  on islemci    KAT metni 3 olarak konuldu
islecin tipe gore secimi      derleyici     tam 3 kesirli 3.5
baska birimdeki islev         baglayici     cagri 7 verdi
veriye bagli dallanma         kosum         buyuk
```

**DD4.** Bu kesit çekirdeğin on dört satırından yalnız dördünü alıyor ve `on_islemci`,
`derleyici`, `baglayici`, `kosum` sayaçlarını hiç taşımıyor — burada amaç dağılımı yeniden
saymak değil, dört sınıfı tek bakışta yan yana koymak. Sayım kesin olarak yalnız önceki
derste yapılır ve orada verilen 4/4/3/3 dağılımı burada değişmez.

Dört satırın her biri, bir önceki bölümdeki "baktığı girdi" tanımını doğruluyor. `makro
degeri` satırı `KAT`in sayısal değerini hiç görmeden, yalnız `3` metnini yerine koyarak
üretildi — ön işlemci `KAT`in bir tam sayı sabiti olduğunu bile bilmez. `islecin tipe gore
secimi` satırı `asama.c`nin kendi içindeki iki değişkenin tipine bakarak üretildi —
`secim.c`nin var olup olmadığının bir önemi yok. `baska birimdeki islev` satırı ise tam
tersini gösteriyor: `kimlik`in gövdesi `asama.c`de hiç yok, yalnız bir bildirim var; kanıt
ancak `secim.c` ile bağlanınca ortaya çıkıyor. `veriye bagli dallanma` satırı da kaynakta
hiçbir sabit sayı taşımıyor; `buyuk` ya da `kucuk` yalnız `veri` dizisinin içeriğine bakılarak
koşumda hesaplanıyor.

Dört satırın hangi sırayla üretildiği de aşamaların sırasını yansıtıyor. Program çalışmaya
başladığında `asama.c` çoktan derlenmiş ve `secim.c` ile bağlanmıştır; koşum yalnız bu bitmiş
programın içinde ilerler. `gozle` çağrılarının kaynaktaki sırası ile çıktının satır sırası
aynı olsa da, bu bir zorunluluk değil bir gözlemdir: dört satırın hangi aşamada karar
verildiği, çıktıda hangi sırada durduklarından bağımsızdır.

İki satır birbirine yakın durabilir ve yine de farklı sınıflara girebilir. Önceki dersin tam
çekirdeğinde `makro degeri` ile `numaralandirma sabiti` ilk bakışta aynı işi yapıyor gibi
görünür — ikisi de bir "sabit değer" üretir. Ama `KAT` bir `#define` olduğu için değeri
kaynağa metin olarak konur ve ön işlemci bunu derleyici hiç devreye girmeden yapar; `MAVI` ise
bir `enum` üyesi olduğu için değeri derleme zamanı sabit ifadesi olarak hesaplanır ve bu
hesap `asama.c`nin kendi birim sınırları içinde kalır. İkisi de kaynakta sabit görünür, ikisi
de koşumda değişmez, ama biri metin düzeyinde bitmiştir, öbürü derleyicinin tip ve ifade
kurallarından geçer. Bu fark, "sabit görünen her şey aynı sınıfa girer" varsayımının neden
yanlış olduğunu gösteriyor: sınıfı belirleyen görünüş değil, kaynaktaki yazım biçimidir.

## Aşamaların Birbirine Kapalılığı

Bir aşamanın diğerine kapalı olması, aralarında bir iletişim kanalı olmadığı anlamına gelir.
Derleyici, ön işlemcinin bir metni neden öyle ürettiğini sormaz; yalnız eline geleni kabul
eder. Bağlayıcı, derleyicinin bir tipi nasıl kontrol ettiğini bilmez; yalnız üretilen
sembolün adına bakar. Koşum ise kaynağın hangi satırdan geldiğini artık taşımaz; elindeki
yalnız makine komutları ve verinin kendisidir.

Bu kapalılığın somut bir sonucu var: bir aşama, bir sonrakine yalnız **kendi çıktısını**
bırakabilir, kendi süreciyle ilgili hiçbir ek bilgi taşıyamaz. Ön işlemci `KAT`in bir makro
olduğunu derleyiciye söylemez, çünkü söyleyecek bir kanalı yoktur — derleyicinin gördüğü
yalnız `3` sayısıdır, sanki kaynakta hep öyle yazılmış gibi. Derleyici de `kimlik`in başka
bir birimde tanımlı olduğunu bağlayıcıya "söylemez"; yalnız kendi ürettiği nesne dosyasına,
çözülmemiş bir ad bırakır ve bağlayıcı bu adı kendi yöntemiyle arar. Her geçişte bir önceki
aşamanın **süreci** kaybolur, yalnız **sonucu** kalır.

Bu, dört sınıfın neden birbirine karışmadığını da açıklıyor. Bir gözlemin hangi sınıfa
girdiğini anlamak için "hangi aşama bu kararı verebilirdi" diye sormak yeterlidir: bir metin
değişimiyse ön işlemci, bir tip veya sabit ifadeyse derleyici, birimler arası bir adsa
bağlayıcı, veriye bakan bir koşulsa koşum. Bu ölçüt yalnız bu derste değil, kursun geri
kalanında da aynı biçimde çalışacak.

Bağlayıcının "yalnız adlara bakması" da aynı kapalılığın bir sonucu. `kimlik` adı `asama.c`
tarafında yalnız bir bildirim olarak durur, `secim.c` tarafında ise bir tanım olarak durur;
bağlayıcının işi bu iki tarafı aynı ad üzerinden eşlemektir. Bunu yaparken `kimlik`in ne iş
yaptığına, gövdesinin ne içerdiğine hiç bakmaz — yalnız adın her iki tarafta da var olup
olmadığını ve varsa kaç kez tanımlandığını denetler. Bir bildirim ile bir tanımın nasıl
ayrıldığı ve bağlayıcının bu ikisini nasıl bir araya getirdiği, sıradaki dersin konusu.

Koşum sınıfının kapalılığı ise en köktenidir. Program çalışmaya başladığında elinde kaynağın
hiçbir izi kalmaz; `veriye bagli dallanma` satırının hangi kaynak satırından geldiğini bilen
hiçbir mekanizma yoktur, çalışan program yalnız kendi verisine ve o verinin ürettiği
sonuçlara bakar. Bu yüzden bir koşum kararını "geriye izleyip" kaynaktaki karşılığını bulmak,
öteki üç aşamadaki gibi doğrudan değildir — kaynakla koşum arasındaki bağ, derleme ve bağlama
sırasında geri dönüşsüz biçimde bir kere kurulmuştur.

## Sınırlayıcı Ölçüm

Aşamalar sırayla çalışır ve geri dönmez: ön işlemcinin ürettiği metin yanlışsa derleyici onu
düzeltmez, yalnız sonucunu görür. Bunu göstermenin en doğrudan yolu, aynı koşullu gövdeyi iki
kez derlemektir — aradaki tek fark kaynağa eklenen bir satır.

Kaynağın farklı gövdeler arasında `#ifdef` ile seçim yapması yaygın bir örüntüdür ve seçim
her zaman ön işlemcide, derleme daha başlamadan karara bağlanır. Önceki dersteki `KAT`
makrosu ve `BIRLESTIR` ad birleştirmesi de aynı sınıftandı: ikisi de derleyici kaynağı
görmeden önce, metin düzeyinde sonuca ulaşmıştı. Aradaki fark şu — `KAT` her zaman aynı
metne açılıyordu, ama `AYRINTILI` tanımlı olup olmaması kaynağın **hangi dalının** derlemeye
gireceğini belirliyor. Bu, tek bir makro değerinden daha güçlü bir örnek: burada seçilen şey
bir sayı değil, kaynağın kendisinin bir parçası.

```c
// gorunum.c — govde secimi kaynakta bir #define ile onceden karara baglanir
#include <stdio.h>

/* AYRINTILI burada tanimli degil: on islemci kisa govdeyi derlemeye sokar. */

int main(void) {
    printf("kosullu govde: ");
#ifdef AYRINTILI
    printf("ayrintili govde derlemeye girdi\n");
#else
    printf("kisa govde derlemeye girdi\n");
#endif
    return 0;
}
```

```
kosullu govde: kisa govde derlemeye girdi
```

```c
// gorunum.c — ayni kosullu blok, govde secimini degistiren tek satir eklendi
#include <stdio.h>

#define AYRINTILI

int main(void) {
    printf("kosullu govde: ");
#ifdef AYRINTILI
    printf("ayrintili govde derlemeye girdi\n");
#else
    printf("kisa govde derlemeye girdi\n");
#endif
    return 0;
}
```

```
kosullu govde: ayrintili govde derlemeye girdi
```

**DD5.** İki dosya da aynı adı taşıyor (`gorunum.c`) ve ikinci blok birinciyi diskte
değiştiriyor; bu, iki ayrı derleme olduğunu, aynı programın iki farklı çalışması olmadığını
göstermek içindir. Aradaki tek fark, ikinci dosyanın başına eklenen tek bir `#define`
satırıdır — gövdenin geri kalanı harfi harfine aynıdır.

`#ifdef` burada koşullu derleme (conditional compilation) ailesinin tek bir üyesidir; aynı
ailede bir adın tanımlı **olmadığını** sınayan `#ifndef` (`asama.h`'nin çifte içermeyi
engellemek için kullandığı yönerge de budur), bir ifadenin değerini sınayan `#if`, başka bir
dalı ekleyen `#elif` ve hiçbirinin doğru olmadığı durumu karşılayan `#else` bulunur. Hepsi
aynı sınıfa girer, çünkü hepsi derleyici devreye girmeden, yalnız ön işlemcinin elindeki
tanımlı adlara bakarak karar verir.

İki derlemenin de kaynağı, satır satır bakıldığında, `#ifdef` bloğunun iki dalını da taşıyor.
Ama derleyici hiçbir zaman iki dalı da görmez: ön işlemci, `AYRINTILI` tanımlı mı diye bakar
ve seçilmeyen dalı **kaynaktan tümüyle siler** — derleyiciye giden metinde o dal artık yoktur,
yorumlanmamış ya da atlanmış değil, hiç yazılmamış gibidir. Derleyici bu yüzden "iki
seçenekten birini eledi" demez; onun gördüğü kaynakta zaten tek bir gövde vardır. Bir
sonraki aşamaya (derleyiciye) geçildiğinde ön işlemcinin verdiği karar artık sorgulanamaz;
tek yol kaynağı değiştirip yeniden en baştan başlamaktır — iki blok arasındaki fark da tam
olarak budur.

Bu, aşamaların neden bir zincir değil bir **tek yönlü sıra** olduğunu gösteriyor. Bir zincirde
her halka bir öncekini denetleyebilir; burada hiçbir aşama bir öncekinin verdiği kararı geri
alamaz, yalnız onun sonucunu devralır. Derleme Aşamaları dersinin adı da buradan geliyor:
aşama, geri dönülebilen bir adım değil, ardışık ve tek yönlü bir sıradır.

Bu tek yönlülüğün pratik bir sonucu var: bir programın verdiği yanlış sonucu ararken, önce o
sonucun hangi aşamada karara bağlandığını sormak aramayı daraltır. `kosullu govde` satırının
yanlış çıktığı görülürse aranacak yer derleyici ya da bağlayıcı değil, kaynaktaki `#define`
satırıdır — çünkü derleyicinin önüne gelen metin zaten tek bir gövdeye indirgenmiştir ve
derleyici o metni doğru yorumlamaktan başka bir şey yapmamıştır. Aynı mantık öteki üç sınıf
için de geçerlidir: bir sınıfın ürettiği sonucun ardında yalnız o sınıfın baktığı girdi
vardır, öncesi değil.

## Özet

- Dört aşama aynı kaynağa bakar ama farklı girdiler görür: ön işlemci metin, derleyici tek
  birim, bağlayıcı birden çok birimin tanımları, koşum ise yalnız veri.
- Küçük bir kesit dört sınıftan birer satırı yan yana koşturdu; her satır kendi sınıfının
  baktığı girdiyi doğruladı.
- Aşamalar sırayla çalışır ve geri dönmez: ön işlemcinin elediği bir dal derleyiciye hiç
  ulaşmaz, derleyici onu "eledi" olarak değil, hiç yokmuş gibi görür.
- Bir aşamanın kararını değiştirmenin tek yolu kaynağı değiştirip zinciri en baştan
  koşturmaktır; hiçbir aşama bir sonrakinden geri dönüş bilgisi almaz.
- Bir hatanın hangi aşamaya ait olduğunu bilmek aramayı daraltır: sonucun ardında yalnız o
  aşamanın baktığı girdi vardır, öncesinde olan biten değil.

## Sonraki Adım

Bağlayıcı sınıfı bu derste yalnız bir çağrıyla gösterildi: `kimlik`in bildirimi bir dosyada,
tanımı başka bir dosyadaydı ve `asama.h` bu bildirimi ikisi arasında taşıyan araç oldu.
Sıradaki ders bu paylaşımın nasıl kurulduğuna bakıyor — bir başlık dosyasının bir bildirimi
birden çok birime nasıl taşıdığı, bildirim ile tanımın neden ayrı tutulması gerektiği ve
bunların birbirine karıştırılmasının nereye kadar zararsız kaldığı.
