---
title: 'Veri Tipleri'
source: 'https://academia.sh/tr/kurslar/c-temelleri/veri-tipleri'
course: 'C Temelleri'
language: tr
updated: '2026-09-13T05:07:32+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Bir tipin taşıdığı değer aralığının derleyicide karara bağlandığını ölçerek gösterir'
    - 'Tam sayı yükseltmesini ve işaretli-işaretsiz dönüşümü örnekle ayırt eder'
    - 'İşaretsiz taşmanın tanımlı sarmasıyla işaretli taşmanın tanımsızlığını birbirinden ayırır'
---

# Veri Tipleri

Bir tipin taşıyabileceği değer aralığının, işaretli-işaretsiz ayrımının ve tam sayı yükseltmesinin derleyicide karara bağlanması; sizeof(char) == 1 dışında hiçbir boyutun basılmaması.

Derleyici Uyarıları ve Standartlar dersi, bir uyarının hangi aşamada doğduğunu ve
standardın neyi garanti edip neyi garanti etmediğini ölçtü: `sizeof(char) == 1` bir
garantiydi, öteki boyutlar değildi. Bu ders o ayrımın üstüne kuruluyor ve daha temel bir
soruyu ölçüyor: bir tip, taşıyabileceği değerlerin sınırını hangi aşamada belirliyor?

Yanıt derleyicidir. Bir kaynak dosyada `int` yazıldığında, o adın taşıyabileceği aralık
ne kaynağın kendisinde ne koşumda; birimin çevrildiği anda, hedef için seçilmiş temsille
birlikte karara bağlanır. **Bu ders M08/K05'te ölçülen "bir tipin hangi sınıf yolunda
bulunması gerektiği" sorusuyla da, M09/K05'te ölçülen "bir bilginin kaynağı" sorusuyla da
karışmaz** — ikisi de bu kursun dışında kalan eksenlerdi; burada ölçülen, bir tipin
taşıdığı değerin hangi aşamada karara bağlandığı ve o kararın sınırlarının nereden
geldiği. Programlama Temelleri kursu (M01/K02) değişken ve tip kavramını Python'la zaten
kurmuştu; orada bir adın hangi değerleri tutabileceği koşum sırasında değişebilirdi, bir
tipin sınırı da ayrıca sorulmazdı. C'de bu iki soru ayrılıyor: tipin kendisi bir sınır
taşıyor ve o sınır kaynakta yazılan tip adıyla birlikte derlemede sabitleniyor. Bir
değişken bildirildikten sonra o değişkenin taşıdığı tip, programın geri kalanı boyunca
değişmez; değer değişebilir, ama değerin hangi aralıkta ve hangi kuralla yorumlanacağını
belirleyen tip sabit kalır. Bu ders o sabitliğin ne anlama geldiğini, dört ayrı kararla —
aralık, yükseltme, işaret ve açık dönüşüm — ölçüyor.

Bu sınırın büyüklüğü hedefe göre değişir ve bu değişkenlik kasıtlıdır: dil, aynı tip
adının farklı donanımlarda farklı genişliklerle temsil edilmesine izin vererek her hedefte
verimli bir eşleşme kurulmasını sağlar. Ama bu esneklik, bir dersin ölçümlerini o hedefe
bağımlı kılmamalı — bir ölçüm burada koşulduğu makinede doğruysa, beş yıl sonra başka bir
hedefte de doğru kalmalı. Bu yüzden bu derste hiçbir gerçek boyut değeri yazdırılmıyor;
onun yerine iki tipin **göreli** ilişkisi ölçülüyor. Bir ilişkinin kendisi de hedeften
hedefe değişebilir, ama belirli bir hedef için derleyicinin verdiği karar sabittir ve
aynı ikili dosya her koşumda aynı ilişkiyi bildirir.

## Boyut Birimi ve Karşılaştırmalı Sonuç

Bir tipin taşıdığı aralığın büyüklüğü hedefe bağlıdır ve bu kursta hiçbir yerde
basılmaz — istisna, standardın açıkça garanti ettiği tek satır: `sizeof(char)` her zaman
`1`dir, çünkü "bayt" ölçü birimi zaten `char` üzerinden tanımlanır. Aşağıdaki ölçüm bu
satırı ve iki tipin göreli büyüklüğünü mantıksal bir sonuçla — büyük mü küçük mü,
`1`/`0` — okuyor; hiçbir gerçek boyut değeri yazdırılmıyor.

```c
// asama.c — tipin tasidigi degerin derleyicide karara baglanmasi
#include <stdio.h>
#include <limits.h>

enum Renk { KIRMIZI = 1, YESIL = 2, MAVI = 4 };

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

int main(void) {
    gozle("tip boyutu birimi", (int)sizeof(char));
    gozle("numaralandirma sabiti", (int)MAVI);
    gozle("int char tan genis mi", (int)(sizeof(int) > sizeof(char)));
    gozle("long int tan genis mi", (int)(sizeof(long) > sizeof(int)));
    gozle("short int tan dar mi", (int)(sizeof(short) < sizeof(int)));

    char kucuk_a = 100, kucuk_b = 100;
    int yukseltilmis_toplam = kucuk_a + kucuk_b;
    gozle("yukseltilmis toplam", yukseltilmis_toplam);

    unsigned char tasan = UCHAR_MAX;
    tasan = (unsigned char)(tasan + 1);
    gozle("isaretsiz tasma sonucu", tasan);

    int eksi = -1;
    unsigned int esik = 1;
    gozle("isaretsize donunce kucuk mu", (int)((unsigned int)eksi < esik));

    return 0;
}
```

```
tip boyutu birimi                 1
numaralandirma sabiti             4
int char tan genis mi             1
long int tan genis mi             1
short int tan dar mi              1
yukseltilmis toplam               200
isaretsiz tasma sonucu            0
isaretsize donunce kucuk mu       0
```

`tip boyutu birimi` satırı standardın garantisini doğruluyor: `char` her zaman tek bayttır
ve bu, kursun ölçtüğü tek boyut değeri kalacak. Geri kalan üç karşılaştırma satırı ise
gerçek bir sayı vermiyor, yalnız bir ilişkinin sonucunu veriyor — hedefte `int` `char`tan
büyük mü, `long` `int`ten büyük mü, `short` `int`ten dar mı diye soruyor ve üçüne de `1`
(doğru) yanıtı geliyor. **TS1.** Bu karşılaştırmaların kendisi de derleyicide karara
bağlanıyor: her ilişki hedeften hedefe değişebilir, ama belirli bir birim çevrilirken
sabittir ve koşum boyunca değişmez — aynı ikili dosya her koşumda aynı `1` ya da `0`
değerini üretir.

Standart bu tiplerin göreli sırasını da zaten garanti eder: `char`, `short`, `int`,
`long` ve `long long` arasındaki genişlik hiçbir zaman geriye doğru olamaz — her biri
kendisinden öncekinin taşıyabildiği her değeri taşıyabilecek genişliktedir. Bu bir ölçüm
değil, dilin kendi belirtimidir; bu ders yalnız belirli bir hedefte bu sıranın **katı**
mı yoksa **eşit** mi gerçekleştiğini ölçüyor (burada üçü de katı çıktı). Bazı hedeflerde
`int` ve `long` aynı genişlikte olabilir — standart yalnız `long`ın `int`ten **dar
olamayacağını** garanti eder, kesinlikle **daha geniş** olacağını değil. Bu derste
ölçülen `1` değeri bu yüzden bu hedefe özgü bir gözlemdir, dilin kendisinin verdiği bir
söz değil.

## Tam Sayı Yükseltmesi

`numaralandirma sabiti` satırı, Derleme Aşamaları dersinde tanıtılan `enum Renk`
sabitinin bir kesitidir: `MAVI` değeri `4`, kaynakta yazılan sabit ifadeden derlemede
üretiliyor. Aynı ölçümde `yukseltilmis toplam` satırı farklı bir kararı gösteriyor:
`kucuk_a` ve `kucuk_b` birer `char`, ama toplamları `char` sınırında değil `int`
sınırında hesaplanıyor. C standardı, `char` ve `short` gibi dar tipleri bir işleme
girmeden önce `int`e **yükseltir** — buna tam sayı yükseltmesi denir. `100 + 100`
işlemi bir `char` üzerinde yürütülseydi (tipik olarak `-128`–`127` aralığında) sonuç
sığmazdı; ama işlem `int` genişliğinde yürüdüğü için `200` sorunsuz çıkıyor. Bu
yükseltme kaynakta görünmez — hiçbir dönüştürme yazılmadı — ama derleyici her `char`
işlenenini işlemden önce `int`e taşıyor ve bu karar tamamen tiplerden geliyor, veriden
değil.

**TS2.** Yükseltme kuralı, işlenen değerin ne olduğuna bakmaksızın uygulanır: `kucuk_a`
ve `kucuk_b` `10` ve `20` olsaydı da toplam yine `int` genişliğinde hesaplanırdı, sonuç
`char` sınırları içinde kalsa bile. Derleyici, işlemi yürütmeden önce hangi genişlikte
çalışacağına yalnız işlenenlerin **tipine** bakarak karar veriyor; bu, işleçlerin veriye
göre değil tipe göre davrandığı ilkenin ilk örneği ve İşleçler dersinde derinleşecek.

Yükseltme yalnız aritmetik işleçlerle sınırlı değildir; bir işlev değişken sayıda
bağımsız değişken aldığında (`printf` bunun standart kitaplıktaki örneğidir) `char` ve
`short` bağımsız değişkenler de çağrı öncesinde `int`e yükseltilir. Buna **varsayılan
bağımsız değişken yükseltmesi** denir ve yalnız `...` kısmına düşen argümanlarda —
prototipin son bildirilen parametresinden sonrasında — işler. `gozle` bundan farklıdır:
prototipli ve sabit imzalı bir işlevdir, dolayısıyla `tasan` değişkeni `unsigned char`
olsa da değer, ikinci parametre `int` bildirildiği için sıradan bir atama dönüşümüyle
`int`e taşınır; `gozle` gövdesindeki `%d` de bu bildirilen tiple eşleşir. İki mekanizma
ayrıdır: biri yalnız değişken argümanlı çağrıların kuyruğunda, öbürü her prototipli
çağrıda işler. Bir dar tipi doğrudan uyuşmayan bir biçim belirleyiciyle yazdırmak
(`unsigned char` için `%hhu` yerine `%d` kullanmak gibi) `printf` tarafında çoğu durumda
varsayılan yükseltme sayesinde çalışır, ama bu kırılgan bir uyumdur ve biçim dizeleri
konusu Girdi/Çıktı dersinde ayrıca ele alınacak.

## Açık Dönüşümle Sınırlama

Yükseltme örtük bir kuraldır — kaynakta hiçbir işaret bırakmadan işler. Ama kaynak yazarı
tam tersini de isteyebilir: geniş bir değeri kasıtlı olarak dar bir tipe sığdırmak. Bu,
açık bir dönüşümle (cast) yapılır ve kararın kendisi yine derlemede, tipin adı yazılırken
veriliyor.

```c
// daraltma.c — acik donusum, sinirlamayi kaynakta gorunur kilar
#include <stdio.h>

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

int main(void) {
    int genis_deger = 300;
    unsigned char daraltilmis = (unsigned char)genis_deger;
    gozle("acikca daraltilan deger", daraltilmis);

    int ikinci_deger = 600;
    unsigned char ikinci_daraltilmis = (unsigned char)ikinci_deger;
    gozle("ikinci acikca daraltilan deger", ikinci_daraltilmis);
    return 0;
}
```

```
acikca daraltilan deger           44
ikinci acikca daraltilan deger    88
```

`300` değeri sekiz bitlik işaretsiz bir tipe sığmıyor, ama dönüşüm yine de tanımlı: aynı
sarma kuralı burada da geçerli ve `300 mod 256 = 44` çıkıyor. `600` için de aynı kural
işliyor ve `88` veriyor. Bu, bir önceki bölümdeki taşmadan farklı bir olay değil, aynı
kuralın kaynakta **açıkça istenerek** tetiklenmiş hali. Örtük yükseltme kaynakta görünmezdi;
açık dönüşüm ise `(unsigned char)` yazımıyla görünür — okuyan kişi, bir daraltmanın
kasıtlı olduğunu kaynaktan anlayabilir. İki durumda da hangi kuralın uygulanacağı, işlenen
değere değil, hedef tipin işaretine bakılarak derlemede belirleniyor.

## İşaretli-İşaretsiz Ayrımı ve Tanımlı Sarma

Bir tipin işaretli mi işaretsiz mi olduğu, taşıdığı aralığın nereden başladığını
belirler ve bu da derlemede karara bağlanan bir özelliktir. `isaretsiz tasma sonucu`
satırı, `unsigned char` tipindeki bir değişkenin üst sınırına (`UCHAR_MAX`) ulaştıktan
sonra bir artırılmasını ölçüyor: sonuç `0`. Bu, bir hata değil — standart, işaretsiz
tipler için taşmayı **tanımlı** kılar: sonuç, tipin temsil edebileceği değer sayısına göre
mod alınarak "sarar." `255 + 1`, sekiz bitlik işaretsiz bir tipte `256 mod 256 = 0` verir
ve bu her koşumda aynı sonucu üretir.

`isaretsize donunce kucuk mu` satırı işaretli-işaretsiz ayrımının başka bir yüzünü
gösteriyor: `-1` değerindeki işaretli bir tamsayı, işaretsiz bir tiple karşılaştırılmadan
önce işaretsize dönüştürülüyor. Bu dönüşüm de tanımlıdır — negatif bir değer işaretsize
dönüştürüldüğünde, tipin temsil edebileceği değer sayısı eklenerek büyük bir işaretsiz
sayıya taşınır. Sonuç olarak `-1`, `esik` değişkenindeki `1`den **küçük değil**, çok daha
büyük görünür ve karşılaştırma `0` (yanlış) döner. Kaynakta yazılan işaretler karşılaştırma
sırasında derleyici tarafından bu şekilde uzlaştırılır; hangi tarafın hangi tipe
dönüştürüleceği veriye değil, iki işlenenin **bildirilen** tipine bakılarak belirlenir.

Bu uzlaştırma kuralı, işaretsiz tiplerin neden sıklıkla sayaç ve boyut taşımak için
tercih edildiğini de açıklıyor: standart kitaplığın `sizeof` işleci `size_t` döndürür ve
bu tip işaretsizdir, çünkü negatif bir boyut kavramsal olarak anlamsızdır. Ama aynı seçim
bir tuzak da taşır. Bir döngü sınırını işaretsiz bir sayaçla geriye doğru yazmak —
`sayac`ı `0`dan aşağı indirmeye çalışmak — sayaç işaretsiz olduğu için hiçbir zaman
negatife düşmez, üst sınırdan sarar ve döngü koşulu hep doğru kalır. Bu durum tanımsız
değildir; sarma kuralı tam olarak yukarıdaki ölçümde görüldüğü gibi işler. Ama sonsuz bir
döngüye yol açacağı için bu ders bu senaryoyu koşturmuyor, yalnız işaretsiz sarmanın bir
sınır koşulunda nasıl **beklenmedik** bir sonuca dönüşebileceğini not ediyor —
davranışın kendisi tanımlı, sonucu yorumlamak kaynağı yazanın işi.

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

Taşma davranışı tipin işaretine bağlıdır ve bu bağımlılık simetrik değildir. İşaretsiz
tipler için taşma yukarıda ölçüldüğü gibi tanımlıdır ve sarma her zaman aynı kurala
uyar. İşaretli bir tipte taşma ise **tanımsız davranıştır**: `INT_MAX` değerindeki bir
`int`i bir artırmak, standardın hiçbir garanti vermediği bir duruma düşer — derleyici bu
durumu varsaymadığı için optimizasyonlar beklenmeyen sonuçlar üretebilir, program
çökebilir ya da hiçbir gözle görülür etki olmayabilir. Bu davranış kursun genel
kuralınca kod bloğunda **denenmiyor**.

Yanına konan tanımlı karşılık, yukarıdaki `unsigned char` ölçümüdür: aynı "üst sınırdan
bir öteye geçme" senaryosu, işaretsiz bir tiple kurulduğunda tam olarak öngörülebilir bir
sonuç veriyor. İki senaryo da aynı soruyu soruyor — tip sınırının ötesine geçilince ne
olur — ama yanıt yalnız işaretin kendisine bağlı: işaretsizde bir aritmetik kural,
işaretlide bir boşluk. Bir tipi işaretli ya da işaretsiz seçmek, bu yüzden yalnız hangi
değerlerin temsil edilebileceğini değil, sınırın aşılması durumunda programın hangi
kategoriye düştüğünü de belirleyen bir karardır ve bu karar tamamen derlemede, kaynakta
yazılan tip adıyla birlikte veriliyor.

Bu asimetrinin kaynağı, iki temsilin donanımdaki karşılığında yatar. İşaretsiz bir tip,
bitlerini doğrudan bir sayının ikili gösterimi olarak okur; sarma, o gösterimin sınırlı
genişliğinin doğal bir sonucudur ve her hedefte aynı biçimde işler. İşaretli bir tipte ise
negatif değerlerin temsili hedefe bağlı olabilir ve taşma durumunda hangi sonucun doğacağını
her temsil için garanti etmek, derleyicinin üst sınıra yakın değerler için yapabileceği
bazı optimizasyonları kısıtlardı. Bu yüzden dil, işaretli taşmayı tanımlamak yerine
tanımsız bırakmayı seçti — davranışı sabitlemek yerine derleyiciye "bu asla olmayacak"
varsayımıyla çalışma özgürlüğü tanıdı.

Bu asimetrinin pratik sonucu, işaretli ve işaretsiz tipler arasında seçim yaparken
yalnız "hangi değerler gerekli" sorusunun değil, "sınır aşılırsa ne olmalı" sorusunun da
sorulması gerektiğidir. Bir sayaç asla negatif olmayacaksa işaretsiz bir tip, hem üst
sınırdan bir bit daha geniş bir aralık kazandırır hem de taşmayı tanımlı bir sarmaya
indirger. Bir hesaplama ise ara adımlarda geçici olarak negatife düşebiliyorsa, işaretli
bir tip bu geçişi doğal biçimde taşır, ama üst sınıra yaklaşan bir toplamda tanımsız
davranışa daha yakın durur. Derleyici bu tercihi kaynak yazarının yerine yapmıyor; yalnız
yazılan tip adını okuyup, o adın taşıdığı sınırı ve sınırın aşılma kuralını sabitliyor.

## Özet

- Bir tipin taşıdığı değer aralığı **derleyicide** karara bağlanır; bu kursta
  `sizeof(char) == 1` dışında hiçbir boyut değeri basılmaz, yalnız karşılaştırma
  sonuçları ölçülür.
- Tam sayı yükseltmesi, `char` ve `short` gibi dar tipleri bir işlemden önce `int`e
  taşır; bu karar işlenen **tiplere** bakılarak verilir, taşınan veriye bakılmaz.
- İşaretsiz tiplerde taşma **tanımlıdır** ve tipin değer sayısına göre sarar; işaretli
  tiplerde taşma **tanımsızdır** ve bu kursta hiçbir kod bloğunda koşturulmaz.
- İşaretli bir değerin işaretsize dönüştürülmesi de tanımlıdır: negatif bir değer, tipin
  değer sayısı eklenerek büyük bir işaretsiz sayıya taşınır.
- Numaralandırma sabitleri (`enum Renk` içindeki `MAVI` gibi) kaynaktaki sabit
  ifadelerden derlemede üretilir; bu konu Yapılar, Birlikler ve Numaralandırmalar
  dersinde derinleşecek.
- Açık bir dönüşüm (`(unsigned char)` gibi), örtük yükseltmenin tersine kaynakta
  görünür ve aynı sarma kuralına tabidir; hangi kuralın uygulanacağı yine hedef tipin
  işaretine bakılarak derlemede belirlenir.

## Sonraki Adım

Bu derste ölçülen her karar tek bir birimin sınırları içinde kaldı: bir tipin aralığı,
bir işlemin genişliği, bir dönüşümün yönü — hepsi aynı dosyaya bakarak, derleyicinin tek
başına verebileceği kararlardı. Bu derste ölçülen tipler zaten var olan
adlara bağlıydı; bir sonraki soru, o adın kendisinin nereden geldiği ve ne kadar
yaşadığıyla ilgili. Bir adın hangi bildirime bağlandığı ve bir değerin ne
kadar yaşadığı her zaman aynı aşamada karara bağlanmaz. Değişkenler, Kapsam ve Ömür dersi
bu ikisini ayırıyor: bir adın nereden göründüğü derlemede sabitlenirken, bir değerin ne
kadar yaşadığı ancak koşum sırasında gözlenebilir — ve ikisi arasındaki fark, aynı adın
iki ayrı birimde iki ayrı nesneye düşebildiği bir üçüncü aşamayı da gündeme getirecek.
