---
title: Taşınabilirlik
source: 'https://academia.sh/tr/kurslar/c-bellek/tasinabilirlik'
course: "C'de Bellek ve İşaretçiler"
language: tr
updated: '2026-09-26T03:02:43+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Adres, tip boyutu ve sıfır boyutlu ayırmanın neden hiç basılmadığını ayırt eder'
    - 'Bir değer yerine standardın garanti ettiği bir karşılaştırmayı basarak hedefe bağlı davranışı yalıtır'
    - 'Kursun on beş dersini sahiplik sınıfına göre tek bir tabloda toplar'
---

# Taşınabilirlik

Ortak tanımın bilerek basmadığı üç değer — adresler, char dışındaki tip boyutları, malloc(0) dönüşü — hedefe bağlıdır; bu ders bir değeri basmak yerine standardın garanti ettiği bir karşılaştırmayı basarak hedefe bağlı davranışı yalıtıyor ve kursun on beş dersini kapanış tablosunda topluyor.

Önceki ders `sinir` parametresinin kaynakta değil çağıranda yazılı olduğunu ölçtü.
Bu ders kursun kendisini kapatıyor ve geriye tek bir soru bırakıyor: ölçüm çekirdeği baştan beri neyi **basmadı**. `sahiplik.c` on üç gözlemi bastı, ama üç şeyi hiç
basmadı — adresler, `sizeof(char)` dışındaki tip boyutları ve `malloc(0)`'ın boş dönüp
dönmediği. Üçü de aynı nedenle dışarıda bırakıldı: üçü de **hedefe bağlıdır**, yani aynı
kaynak metin iki farklı hedefte iki farklı sayı üretebilir.

Bu ders o üç değeri basmaya çalışmıyor. Onun yerine standardın **garanti ettiği** bir
karşılaştırmayı basıyor. Aradaki fark şu: `sizeof(int)`'i basmak bir sayı verir ve o sayı
hedefe göre değişir; `sizeof(char) == 1` sorusunu sormak da bir sonuç verir, ama bu sonuç
her hedefte **aynıdır**, çünkü standardın kendisi bunu garanti eder. Ölçülen şey aynı
soruya iki farklı yaklaşım değil — biri hedefe bağlı bir değeri açığa çıkarır, öteki
standardın hedeften bağımsız bıraktığı mantıksal sonucu açığa çıkarır. Bu dersin sahiplik
sınıfı **dil**dir: garantiyi veren taraf çağıran, çağrılan ya da sahipsiz kalan bir blok
değil, dilin standardının kendisidir.

## Üç Karşılaştırma, Tek Yalıtım Tekniği

Ölçüm çekirdeğinin sayaç birimi bu derste de kullanılıyor; kesiti aşağıda, yeniden
yazılmadan.

```c
// sayac.h — her ayirmayi ve her birakmayi sayan sarmalayici
#ifndef SAYAC_H
#define SAYAC_H

#include <stddef.h>

void *say_ayir(size_t boyut);
void *say_buyut(void *eski, size_t boyut);
void say_birak(void *blok);
int ayrilan_sayisi(void);
int birakilan_sayisi(void);

#endif
```

```c
// sayac.c — sayaclar yalniz bu birimde tutulur
#include <stdlib.h>
#include "sayac.h"

static int ayrilan = 0;
static int birakilan = 0;

void *say_ayir(size_t boyut) {
    void *blok = malloc(boyut);
    if (blok != NULL) {
        ayrilan++;
    }
    return blok;
}

void *say_buyut(void *eski, size_t boyut) {
    int yeni_blok = (eski == NULL);
    void *yeni = realloc(eski, boyut);
    if (yeni != NULL && yeni_blok) {
        ayrilan++;
    }
    return yeni;
}

void say_birak(void *blok) {
    if (blok != NULL) {
        birakilan++;
    }
    free(blok);
}

int ayrilan_sayisi(void) {
    return ayrilan;
}

int birakilan_sayisi(void) {
    return birakilan;
}
```

**SL10.** `sayac.c` bu derste de aynı davranışı sürdürüyor: `say_ayir` yalnız dönüş
`NULL` değilse sayacı artırıyor, `say_birak` yalnız `NULL` değilse sayacı artırıp yine de
`free`'yi çağırıyor. Bu iki satır bu dersin son gözlemi için önceden kuruluyor — `boyut`
sıfır olduğunda `malloc`'ın ne döndüreceği hedefe bağlı olsa da, `sayac.c`'nin bu iki
satırının davranışı **değişmiyor**.

Yeni dosya üç karşılaştırmayı ve sıfır boyutlu ayırmayı bir arada ölçüyor. Hiçbir satır bir
boyutu, bir sınır değerini ya da bir adresi basmıyor; her satır yalnız bir karşılaştırmanın
sonucunu basıyor.

```c
// tasinirlik.c — bir degeri basmak yerine standardin garantisini basar
#include <stdint.h>
#include <limits.h>
#include <stdio.h>
#include "sayac.h"

static void gozle(const char *ad, const char *sonuc) {
    printf("%-34s%s\n", ad, sonuc);
}

int main(void) {
    printf("%-34s%s\n", "gozlem", "sonuc");

    gozle("sabit genislikli tam sayi", sizeof(int32_t) * CHAR_BIT == 32 ? "garanti tutuyor" : "garanti tutmuyor");
    gozle("char boyutu", sizeof(char) == 1 ? "garanti tutuyor" : "garanti tutmuyor");
    gozle("int alt siniri", INT_MAX >= 32767 ? "garanti tutuyor" : "garanti tutmuyor");

    int birinci = 7;
    int ikinci = 7;
    int *aynisi = &birinci;
    int *tekrar = &birinci;
    int *ayrisi = &ikinci;
    gozle("ayni degiskenin iki adresi", aynisi == tekrar ? "esit" : "esit degil");
    gozle("iki ayri degiskenin adresi", aynisi == ayrisi ? "esit" : "esit degil");

    int once = ayrilan_sayisi() - birakilan_sayisi();
    void *sifir_boyut = say_ayir(0);
    say_birak(sifir_boyut);
    int sonra = ayrilan_sayisi() - birakilan_sayisi();
    gozle("sifir boyutlu ayirma sozlesmesi", sonra - once == 0 ? "sozlesme saglandi" : "sozlesme bozuldu");

    return 0;
}
```

```
gozlem                            sonuc
sabit genislikli tam sayi         garanti tutuyor
char boyutu                       garanti tutuyor
int alt siniri                    garanti tutuyor
ayni degiskenin iki adresi        esit
iki ayri degiskenin adresi        esit degil
sifir boyutlu ayirma sozlesmesi   sozlesme saglandi
```

**SL11.** İlk üç satır aynı kalıbı izliyor: bir tip boyutunu ya da bir sınır değerini
doğrudan basmak yerine, standardın zaten garanti ettiği bir alt sınırla karşılaştırıyor.
`int32_t` var olduğunda tam olarak otuz iki bit genişliğindedir — bu, tanımın kendisinden
gelir, hedeften değil. Karşılaştırmanın bayt sayısıyla değil bit sayısıyla kurulmasının nedeni
de budur: bir bayttaki bit sayısı (`CHAR_BIT`) standartta yalnız en az sekiz olarak garanti
edilir, bu yüzden `sizeof(int32_t)` hedeften hedefe değişebilir, `sizeof(int32_t) * CHAR_BIT`
ise değişmez. `sizeof(char)` her zaman birdir — bu da tanımdan gelir; kursun başından beri
`sizeof(char)` dışındaki hiçbir boyutun basılmamasının nedeni tam olarak budur. `INT_MAX`
standart tarafından en az `32767` olacak şekilde garanti edilir; gerçek değeri hedefe göre
daha büyük olabilir, ama bu alt sınırın **tutup tutmadığı** her hedefte aynı sonucu verir.

**SL12.** Dördüncü ve beşinci satır adresleri basmadan işaretçi eşitliğini ölçüyor. `aynisi`
ile `tekrar` aynı değişkenin adresini tutuyor; ikisinin eşitliği bir dil kuralından gelir —
aynı ifade (`&birinci`) her değerlendirildiğinde aynı sonucu verir. `aynisi` ile `ayrisi` ise
aynı anda yaşayan iki ayrı otomatik nesnenin adreslerini tutuyor; standart bu iki nesnenin
çakışmayacağını garanti eder, bu yüzden eşitsizlik de bir uygulama tesadüfü değil, bir dil
garantisidir. İki satır da adresin **kendisini** hiç göstermeden bu iki garantiyi ölçüyor.

**SL13.** Son satır ortak tanımın üçüncü basılmayanını ele alıyor: `malloc(0)`'ın boş
döndürüp döndürmediği hedefe bağlıdır ve bu ders o soruyu **yanıtlamıyor**. Bunun yerine
`sayac.c`'nin iki satırının bu belirsizlikten etkilenip etkilenmediğini ölçüyor. `say_ayir(0)`
`NULL` dönerse sayaç hiç artmaz ve `say_birak(NULL)` da hiç artırmaz — fark sıfır kalır.
`say_ayir(0)` geçerli bir işaretçi dönerse sayaç bir artar ve `say_birak` onu bırakırken
sayaç da bir artar — fark yine sıfır kalır. `malloc(0)`'ın hangi dalı izlediği hiçbir zaman
görünmüyor; görünen tek şey, sözleşmenin **her iki dalda da** aynı kaldığıdır.

## Sabit Genişlikli Tiplerin Kendi Sınırı

`<stdint.h>`'ın sunduğu yalıtım kendi başına sınırsız değil. Standart, `int32_t` gibi tam
genişlikli tipleri yalnız hedef platformda öyle bir tip **varsa** tanımlamayı zorunlu kılar;
yokluğunda bu tipler hiç tanımlanmaz ve onları kullanan bir kaynak dosya derlenmez. Standart,
her hedefte bulunmasını zorunlu kıldığı tipleri ayrı adlarla verir — `int_least32_t` en az
otuz iki bit genişliğinde olmayı garanti eder, `int32_t` ise tam olarak otuz iki bit
genişliğinde olmayı, ama yalnız var olduğunda.

**SL14.** Bu derste `int32_t`'nin varlığını sınamak yerine doğrudan kullanılması, dersin
kendisinin bir varsayımı: dersin derlendiği ortamda bu tip **var**. Yalıtım tekniğinin
kendisi de böylece bir varsayıma yaslanıyor — genişliğin değil, tipin **varlığının**
varsayımına. Tam genişliğin gerekmediği bir yerde taşınabilir bir kaynak `int_least32_t` ya da
`int_fast32_t` kullanır; bu ders `int32_t`'yi yalnız örnek için seçti.

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

Bir değeri basmak yerine bir garantiyi basmak, hedefe bağlı olanı **ortadan kaldırmaz** —
yalnız onu gözlemin dışına taşır. `sizeof(int32_t) * CHAR_BIT == 32` ifadesi her hedefte aynı
sonucu verir, ama bunu yalnızca `int32_t` **var olduğunda** yapar; standardın kendisi bu tipin
var olmasını zorunlu kılmaz. Aynı biçimde `INT_MAX >= 32767` her hedefte tutar, ama gerçek
`INT_MAX` değeri hedeften hedefe değişebilir — ders bu değeri hiç basmayarak taşınırlığı
korur, ama sınamak istediği asıl soruyu (`INT_MAX` tam olarak kaçtır) yanıtsız bırakır. Bir
karşılaştırma bir değerden daha taşınabilirdir, ama daha az bilgi taşır; taşınabilirlik ile
bilgi arasındaki bu değiş tokuş, dilin garantisinin **nerede bittiğini** işaretler. Ölçüm
çekirdeğinin dört sınıfından hiçbiri bu değiş tokuşu ortadan kaldırmaz — dil sınıfı da dahil,
çünkü garantiyi veren dil, garantinin kapsamını da kendisi çizer.

## Özet

- Bu dersin ölçtüğü bellek sınıfı **dil**dir: garantiyi veren taraf çağıran, çağrılan ya da
  sahipsiz kalan bir blok değil, dilin standardının kendisidir.
- Ortak tanımın bilerek basmadığı üç değer — adresler, `sizeof(char)` dışındaki tip
  boyutları, `malloc(0)`'ın dönüşü — üçü de hedefe bağlıdır ve bu derste de basılmadı.
- Bir değer yerine standardın garanti ettiği bir karşılaştırma basıldığında sonuç her
  hedefte aynı kalır; `sizeof(int32_t) * CHAR_BIT == 32`, `sizeof(char) == 1` ve
  `INT_MAX >= 32767` üçü de bu kalıbı izledi.
- Aynı anda yaşayan iki otomatik nesnenin adresleri çakışmaz; bu eşitsizlik adresin kendisi
  hiç basılmadan, yalnız `==` karşılaştırmasıyla ölçüldü.
- `malloc(0)`'ın boş dönüp dönmediği hedefe bağlı kalsa da, `sayac.c`'nin ayırma-bırakma
  sözleşmesi bu belirsizlikten etkilenmedi: fark her iki dalda da sıfır kaldı.
- Bir garantiyi basmak hedefe bağlı olanı ortadan kaldırmaz, yalnız gözlemin dışına taşır —
  `int32_t`'nin kendisi de var olmayabilecek bir tiptir.

## Kurs Kapanışı

Kurs boyunca tek bir soru soruldu: bu belleği kim sahipleniyor. On dört ders bu soruyu dört
sınıfla yanıtladı — dil, çağıran, çağrılan, sahipsiz — ve bu ders, aynı sorunun dilin
kendisine sorulduğunda ne söylediğini gösterdi: standardın garanti ettiği yerde dil
sahiplenir, garantinin bittiği yerde gözlem hedefe bağlı kalır ve basılmaz.

| Ders | Ölçülen bellek | Sahibi | Sınırlayıcı ölçüm |
|---|---|---|---|
| İşaretçi Temelleri | Yerel değişken, statik alan, dizgi değişmezi, yerel dizi | dil | Bir işaretçinin tipi kimin bırakacağını söylemez |
| İşaretçi Aritmetiği | Dizi içi ilerleme ve eleman farkı | dil | Sınırın bir ötesini göstermek geçerlidir, dolaylamak tanımsızdır |
| Diziler ve İşaretçiler | Dinamik olarak ayrılmış dizi | çağıran | Bozunma yalnız bir düzeyde çalışır, eleman sayısını taşımaz |
| Boş ve Sarkan İşaretçiler | Bırakılmış bloğu gösteren işaretçi | sahipsiz | NULL atamak yalnız o işaretçiyi denetlenebilir kılar, aynı bloğu gösteren başka bir işaretçiyi etkilemez |
| `void` ve Opak İşaretçiler | Opak kayıt (`Kayit`) | çağrılan | Opaklık yapının içini gizler, sahipliği gizlemez: bırakma yükümlülüğü yalnız yorumda yazılıdır |
| Fonksiyon İşaretçileri | Geri çağrıya taşınan bağlam | çağıran | Bir imza davranışı garanti etmez, yalnız tip uyumunu denetler |
| Bellek Ayırma İşlevleri | `malloc`/`calloc`/`realloc` ile ayrılan blok | çağıran | `malloc(0)` ve `realloc(blok, 0)` dönüşü hedefe bağlıdır, hiç basılmaz |
| Serbest Bırakma Disiplini | Ödünç verilen ad ile döndürülen kopya | çağrılan | Sahiplik imzadan değil, başlık dosyasındaki yorumdan anlaşılır |
| Bellek Sızıntıları | Sahiplenilmeyen iki blok | sahipsiz | Sızıntı çökme ya da uyarı üretmez, yalnız sayaç farkıyla görünür |
| Bellek Hata Ayıklama Araçları | Dengeli ve dengesiz ayırma-bırakma çifti | sahipsiz | Bir araç yalnız eşleşmeyen çağrıyı sayar, sözleşme ihlalini okumaz |
| Bellek Düzeni | Dört bellek bölgesindeki değişken | dil | Bölge sınırları ve hizalama basılmaz; öbek dışında sahiplik bölgeden değil sözleşmeden gelir |
| Tanımsız Davranış | Dört tanımsız işlemin tanımlı karşılığı | sahipsiz | Çalışıyor görünmek tanımlı olduğunu göstermez |
| Hata Yönetimi Kalıpları | Hata yolunda temizlenen blok | çağrılan | Kısmi başarısızlıkta kimin temizleyeceği her işlevde ayrı yazılmalıdır |
| Sınır Denetimi | `snprintf` ile sınırlanan kopya | çağıran | İşlev yalnız kendisine söylenen sınırı denetler, yanlış bildirilen sınırı yakalayamaz |
| Taşınabilirlik | Sabit genişlikli tip, `sizeof(char)`, `INT_MAX`, sıfır boyutlu ayırma | dil | Yalıtım tekniğinin kendisi de bir garantiye dayanır: `int32_t`'nin var olması standart tarafından zorunlu değildir |

Dersler sınıflara **4 dil · 4 çağıran · 3 çağrılan · 4 sahipsiz** olarak dağılıyor — bu
derslerin dağılımıdır ve çekirdeğin on üç gözleminin 4/4/3/2'siyle karıştırılmaz.

Dört sınıf on beş ders boyunca hiç değişmedi, ama her ders sınıfı farklı bir yüzden gösterdi:
kimi zaman sahiplenen taraf bir işlevdi, kimi zaman bir sözleşmeydi, kimi zaman hiç kimseydi,
kimi zaman da bu son derste görüldüğü gibi dilin kendisiydi. Bir işaretçinin tipi hiçbir
zaman sahibini söylemedi; sahibi her seferinde ya kaynağın kendisi (bir `&` ifadesi, bir
ayırma çağrısı) ya da başlık dosyasındaki yazılı sözleşme belirledi.

Sıradaki kurs C ile sistem programlamaya, işletim sistemi arayüzlerine bakıyor. Bu kursun
sahiplik sorusu orada da geçerliliğini koruyor — bir dosya tanıtıcısını, bir süreci ya da bir
sinyali kim sahipleniyor sorusu, bellek için sorulan soruyla aynı biçimdedir; ama bu kaynakların
sınıflarını o kurs kendi ölçümüyle kuracak.
