Temel Veri Tipleri
Programlama bir nevi kutulara eşya yerleştirmeye benzer. Küçük bir yüzük için kocaman bir bavul kullanmazsın, değil mi? C++'ta veri tipleri de tam olarak bu mantıkla çalışır: her veri tipi farklı boyutta bir "kutu" ve içine koyabileceğin şeylerin türü ve büyüklüğü o kutuya göre değişir.
Bu derste C++'ın temel yapı taşları olan veri tiplerini tanıyacağız. Hangi tipi ne zaman kullanman gerektiğini, bellekte ne kadar yer kapladıklarını ve aralarındaki farkları öğreneceksin.
Neden Veri Tipleri Önemli?
Bilgisayarın belleği sınırlıdır. Her değişken tanımladığında, bellekten bir parça ayırıyorsun. Eğer sadece bir kişinin yaşını tutacaksan, 8 byte'lık bir long long kullanmak israf olur. Ama bir galaksideki yıldız sayısını tutacaksan, short yetmez.
C++ "statik tipli" (statically typed) bir dildir. Yani bir değişkenin tipini en baştan belirlersin ve o tip programın sonuna kadar değişmez. Python gibi dillerde tip otomatik belirlenir ama C++'ta sen söylersin.
Bu hem avantaj hem sorumluluk: derleyici hataları erkenden yakalar, ama sen de doğru tipi seçmek zorundasın.
Tam Sayı Tipleri (Integer Types)
Tam sayılar, ondalık kısmı olmayan sayılardır: 1, 42, -7, 0 gibi. C++ sana farklı boyutlarda tam sayı kutuları sunar.
int — Günlük Kullanımın Yıldızı
int en yaygın kullanılan tam sayı tipidir. Çoğu platformda 4 byte (32 bit) yer kaplar.
#include <iostream>
int main() {
int yas = 25;
int sicaklik = -5;
int ogrenci_sayisi = 1500;
std::cout << "Yas: " << yas << std::endl;
std::cout << "Sicaklik: " << sicaklik << std::endl;
std::cout << "Ogrenci: " << ogrenci_sayisi << std::endl;
return 0;
}int yaklaşık -2.1 milyar ile +2.1 milyar arasında değer tutabilir. Günlük programlamada bu aralık çoğu iş için fazlasıyla yeterlidir.
short — Küçük Kutu
short genelde 2 byte (16 bit) yer kaplar. -32,768 ile 32,767 arasında değer tutar.
#include <iostream>
int main() {
short kucuk_sayi = 30000;
// short tasma = 40000; // Uyari! 32767'yi asar
std::cout << "Kucuk sayi: " << kucuk_sayi << std::endl;
return 0;
}Bellek çok kısıtlı ortamlarda (gömülü sistemler gibi) veya binlerce küçük sayı tutman gerektiğinde short işine yarar. Ama modern bilgisayarlarda genelde int kullanırsın.
long ve long long — Büyük Sayılar İçin
long en az 4 byte, long long en az 8 byte yer kaplar. Çok büyük sayılarla çalışırken long long tercih edilir.
#include <iostream>
int main() {
long buyuk = 2000000000L;
long long cok_buyuk = 9000000000000000000LL;
std::cout << "long: " << buyuk << std::endl;
std::cout << "long long: " << cok_buyuk << std::endl;
return 0;
}long long ile yaklaşık ±9.2 kentilyon (9.2 × 10¹⁸) arasında değer tutabilirsin. Finansal hesaplamalar, büyük veri setleri veya bilimsel hesaplamalar için idealdir.
💡 İpucu: Sayı sabitlerinin (literal) sonuna
LveyaLLeklemek, derleyiciye o sayınınlongveyalong longolduğunu söyler.42Lbir long,42LLbir long long'dur.
Tam Sayı Tipleri Karşılaştırma Tablosu
| Tip | Minimum Boyut | Tipik Boyut | Aralık (tipik) |
|---|---|---|---|
short | 2 byte | 2 byte | -32,768 → 32,767 |
int | 2 byte | 4 byte | -2.1 milyar → 2.1 milyar |
long | 4 byte | 4 veya 8 byte | Platform bağımlı |
long long | 8 byte | 8 byte | ±9.2 × 10¹⁸ |
⚠️ Dikkat: C++ standardı bu tiplerin *minimum* boyutlarını garanti eder, tam boyutlarını değil. Yani
intbir platformda 2 byte, başka bir platformda 4 byte olabilir. Kesin boyut istiyorsan<cstdint>başlık dosyasındaki tipleri kullan.
Sabit Boyutlu Tam Sayılar (Fixed-Width Integers)
Platformdan bağımsız, kesin boyut istiyorsan <cstdint> başlık dosyasını kullanabilirsin:
#include <iostream>
#include <cstdint>
int main() {
int8_t kucuk = 127; // Tam 1 byte
int16_t orta = 32000; // Tam 2 byte
int32_t buyuk = 2000000000; // Tam 4 byte
int64_t dev = 9000000000000000000LL; // Tam 8 byte
std::cout << "int8: " << static_cast<int>(kucuk) << std::endl;
std::cout << "int16: " << orta << std::endl;
std::cout << "int32: " << buyuk << std::endl;
std::cout << "int64: " << dev << std::endl;
return 0;
}Bu tipler özellikle ağ programlama, dosya formatları ve platformlar arası taşınabilirlik gereken durumlarda çok işe yarar.
signed vs unsigned — İşaretli ve İşaretsiz
Varsayılan olarak tam sayı tipleri "signed"dır, yani hem pozitif hem negatif değer tutabilirler. unsigned anahtar kelimesiyle sadece pozitif (ve sıfır) değer tutan bir tip elde edersin.
#include <iostream>
int main() {
int normal = -42; // -2.1 milyar ile +2.1 milyar
unsigned int pozitif = 42; // 0 ile ~4.2 milyar
std::cout << "signed: " << normal << std::endl;
std::cout << "unsigned: " << pozitif << std::endl;
// Tehlikeli durum:
unsigned int dikkat = 0;
dikkat = dikkat - 1; // 0'dan 1 cikarinca ne olur?
std::cout << "Surpriz: " << dikkat << std::endl; // 4294967295!
return 0;
}unsigned bir değişkenden 0'ın altına inersen, sayı taşması (overflow) olur ve çok büyük bir pozitif sayı elde edersin. Bu, C++'taki en sinsi hatalardan biridir.
Ne Zaman unsigned Kullanmalı?
Bit manipülasyonu yapıyorsan
Bir dizinin boyutu gibi doğası gereği negatif olamayacak değerler için
Standart kütüphanenin
size_tgibi tipleriyle çalışırken
Ama genel kurala dikkat: emin değilsen `signed` (yani normal `int`) kullan. Unsigned ile signed karıştırmak karşılaştırma hatalarına yol açar.
⚠️ Dikkat:
unsigned intileintkarşılaştırması beklenmedik sonuçlar doğurabilir. Derleyiciler genelde bu konuda uyarı verir — uyarıları ciddiye al!
Ondalıklı Sayı Tipleri (Floating-Point Types)
Gerçek dünyada her şey tam sayı değildir. Sıcaklık 36.6 derece olabilir, pi sayısı 3.14159... diye devam eder. İşte bu tür sayılar için ondalıklı (floating-point) tipler kullanırız.
float — Tek Hassasiyet (Single Precision)
float 4 byte yer kaplar ve yaklaşık 6-7 basamak hassasiyet sağlar.
#include <iostream>
#include <iomanip>
int main() {
float pi = 3.14159265f; // 'f' soneki float oldugunu belirtir
float sicaklik = 36.6f;
std::cout << std::setprecision(10);
std::cout << "Pi (float): " << pi << std::endl;
// Cikti: 3.141592741 — 7. basamaktan sonra sapma baslar!
return 0;
}Gördüğün gibi, float 7. basamaktan sonra "sallamaya" başlıyor. Bu normal — floating-point sayılar doğası gereği yaklaşık değerlerdir.
double — Çift Hassasiyet (Double Precision)
double 8 byte yer kaplar ve yaklaşık 15-16 basamak hassasiyet sağlar. C++'ta ondalıklı sayılar için varsayılan tip double'dır.
#include <iostream>
#include <iomanip>
int main() {
double pi = 3.141592653589793;
float pi_f = 3.141592653589793f;
std::cout << std::setprecision(16);
std::cout << "Pi (double): " << pi << std::endl;
std::cout << "Pi (float): " << pi_f << std::endl;
return 0;
}long double — Ekstra Hassasiyet
long double platformdan platforma değişir (8, 12 veya 16 byte olabilir). Çoğu programcı double ile yetinir, long double çok nadir kullanılır.
float vs double Karşılaştırma
| Özellik | float | double |
|---|---|---|
| Boyut | 4 byte | 8 byte |
| Hassasiyet | ~7 basamak | ~15 basamak |
| Aralık | ±3.4 × 10³⁸ | ±1.7 × 10³⁰⁸ |
| Kullanım | Grafik, oyun, GPU | Genel amaçlı, bilimsel |
💡 İpucu: Emin değilsen
doublekullan.floatsadece belleğin çok kısıtlı olduğu veya GPU hesaplaması yaptığın durumlarda tercih edilir. Derleyici de zaten ondalıklı sabitleri varsayılan olarakdoublekabul eder.
Floating-Point Tuzakları
Ondalıklı sayılarla çalışırken en önemli kural: tam eşitlik karşılaştırması yapma!
#include <iostream>
#include <cmath>
int main() {
double a = 0.1 + 0.2;
double b = 0.3;
// YANLIS — beklenmedik sonuc verebilir
if (a == b) {
std::cout << "Esit" << std::endl;
} else {
std::cout << "Esit degil!" << std::endl; // Bu calisir!
}
// DOGRU — epsilon ile karsilastir
double epsilon = 1e-9;
if (std::abs(a - b) < epsilon) {
std::cout << "Yaklasik esit" << std::endl; // Bu calisir
}
return 0;
}0.1 + 0.2 tam olarak 0.3 etmez! Bu, floating-point aritmetiğinin doğasından kaynaklanır. İkili (binary) sistemde 0.1 sonsuz tekrarlı bir sayıdır — tıpkı 1/3'ün onluk sistemde 0.333... olması gibi.
Karakter Tipi — char
char tek bir karakter tutar ve 1 byte (8 bit) yer kaplar. Karakterler aslında sayı olarak saklanır — ASCII tablosuna göre.
#include <iostream>
int main() {
char harf = 'A';
char rakam = '7';
char ozel = '\n'; // Yeni satir karakteri
std::cout << "Harf: " << harf << std::endl;
std::cout << "ASCII degeri: " << static_cast<int>(harf) << std::endl;
// Cikti: 65
// char aslinda bir sayi!
char sonraki = harf + 1;
std::cout << "Sonraki: " << sonraki << std::endl;
// Cikti: B
return 0;
}char ile aritmetik yapabilirsin çünkü temelde bir sayıdır. 'A' + 1 sana 'B' verir, çünkü ASCII tablosunda A=65, B=66.
Özel Karakterler (Escape Sequences)
| Kaçış Dizisi | Anlamı |
|---|---|
\n | Yeni satır |
\t | Tab |
\\ | Ters eğik çizgi |
\' | Tek tırnak |
\" | Çift tırnak |
\0 | Null karakter (string sonu) |
char8_t, char16_t, char32_t — Unicode Destekleri
Modern C++ Unicode için ek karakter tipleri sunar:
#include <iostream>
int main() {
char ascii = 'A'; // 1 byte, ASCII
char16_t unicode16 = u'Ş'; // 2 byte, UTF-16
char32_t unicode32 = U'🎮'; // 4 byte, UTF-32
std::cout << "ASCII boyut: " << sizeof(ascii) << std::endl;
std::cout << "char16 boyut: " << sizeof(unicode16) << std::endl;
std::cout << "char32 boyut: " << sizeof(unicode32) << std::endl;
return 0;
}Türkçe karakterler veya emoji gibi ASCII dışı karakterlerle çalışıyorsan bu tipleri bilmen faydalı olur. Ama günlük işlerde genelde std::string ve UTF-8 kullanırsın.
Mantıksal Tip — bool
bool sadece iki değer alabilir: true (doğru) veya false (yanlış). Genelde 1 byte yer kaplar.
#include <iostream>
int main() {
bool aktif = true;
bool silindi = false;
bool yetiskin = (18 <= 25); // true
std::cout << std::boolalpha; // true/false yazdirir (1/0 yerine)
std::cout << "Aktif: " << aktif << std::endl;
std::cout << "Silindi: " << silindi << std::endl;
std::cout << "Yetiskin: " << yetiskin << std::endl;
// bool aritmetikte sayi gibi davranir
int toplam = aktif + silindi + yetiskin;
std::cout << "Toplam (true sayisi): " << toplam << std::endl;
// true=1, false=0, true=1 → toplam=2
return 0;
}bool aritmetik ifadelerde true → 1, false → 0 olarak davranır. Koşul ifadelerinde (if, while) en çok kullanılan tiptir.
💡 İpucu:
std::boolalphamanipülatörünü kullanmazsan,coutbool değerleri1ve0olarak yazdırır. Okunabilirlik içinboolalphatercih edilir.
sizeof() Operatörü
sizeof() bir tipin veya değişkenin bellekte kaç byte yer kapladığını söyler. Derleme zamanında (compile-time) hesaplanır, yani programın çalışma hızını etkilemez.
#include <iostream>
int main() {
std::cout << "char: " << sizeof(char) << " byte" << std::endl;
std::cout << "short: " << sizeof(short) << " byte" << std::endl;
std::cout << "int: " << sizeof(int) << " byte" << std::endl;
std::cout << "long: " << sizeof(long) << " byte" << std::endl;
std::cout << "long long: " << sizeof(long long) << " byte" << std::endl;
std::cout << "float: " << sizeof(float) << " byte" << std::endl;
std::cout << "double: " << sizeof(double) << " byte" << std::endl;
std::cout << "bool: " << sizeof(bool) << " byte" << std::endl;
// Degiskenle de kullanilabilir
int x = 42;
std::cout << "x: " << sizeof(x) << " byte" << std::endl;
return 0;
}Tipik bir 64-bit Linux/Windows sisteminde çıktı şöyle olur:
char: 1 byte
short: 2 byte
int: 4 byte
long: 4 byte (Windows) veya 8 byte (Linux)
long long: 8 byte
float: 4 byte
double: 8 byte
bool: 1 bytesizeof bir fonksiyon değil, bir operatördür. Tip ismiyle kullanırken parantez zorunludur (sizeof(int)), ama değişkenle kullanırken opsiyoneldir (sizeof x de çalışır — yine de parantez kullanmak daha okunabilir).
Tip Sınırlarını Öğrenmek — numeric_limits
Her tipin alabildiği minimum ve maksimum değerleri <limits> başlık dosyasıyla öğrenebilirsin:
#include <iostream>
#include <limits>
int main() {
std::cout << "int min: "
<< std::numeric_limits<int>::min() << std::endl;
std::cout << "int max: "
<< std::numeric_limits<int>::max() << std::endl;
std::cout << "double min: "
<< std::numeric_limits<double>::min() << std::endl;
std::cout << "double max: "
<< std::numeric_limits<double>::max() << std::endl;
std::cout << "float hassasiyet (digits10): "
<< std::numeric_limits<float>::digits10 << std::endl;
std::cout << "double hassasiyet (digits10): "
<< std::numeric_limits<double>::digits10 << std::endl;
return 0;
}digits10 bir tipin güvenilir şekilde temsil edebileceği ondalık basamak sayısını verir. float için 6, double için 15.
void — "Hiçlik" Tipi
void aslında bir veri tipi değildir — "tip yok" anlamına gelir. Değişken tanımlamak için kullanamazsın ama iki yerde karşına çıkar:
Fonksiyonlar: Değer döndürmeyen fonksiyonlar
voiddönerPointer'lar:
void*herhangi bir tipe işaret edebilir (ileri konular)
#include <iostream>
void selamla() { // Deger dondurmuyor
std::cout << "Merhaba!" << std::endl;
}
int main() {
selamla();
// void x = 5; // HATA! void degisken olamaz
return 0;
}void şimdilik sadece "bir fonksiyon değer döndürmüyorsa void yazılır" bilgisi yeterli. İlerleyen derslerde fonksiyonlar konusunda detaylı göreceksin.
Doğru Tipi Nasıl Seçerim?
Pratik bir karar ağacı:
Tam sayı mı?
- Normal aralıkta → int - 2 milyarı aşabilir → long long - Çok küçük ve bellek kritik → short - Kesin boyut lazım → int32_t, int64_t
Ondalıklı sayı mı?
- Genel amaçlı → double - GPU / grafik / bellek kritik → float
Karakter mi?
- ASCII → char - Unicode → char32_t veya std::string (UTF-8)
Evet/Hayır mı?
- → bool
Emin değil misin?
- Tam sayı → int - Ondalıklı → double
Sayı Sabitleri (Literals) ve Ayraçlar
C++14'ten itibaren büyük sayıları okunabilir kılmak için tek tırnak ayraç kullanabilirsin:
#include <iostream>
int main() {
int milyon = 1'000'000; // Okunaklı!
long long buyuk = 9'223'372'036'854'775'807LL;
double pi = 3.141'592'653'589'793;
// Farkli tabanlarda sabitler
int onluk = 42; // Decimal
int sekizlik = 052; // Octal (0 ile baslar)
int onaltilik = 0x2A; // Hexadecimal (0x ile baslar)
int ikilik = 0b101010; // Binary (0b ile baslar, C++14)
std::cout << "Hepsi 42: "
<< onluk << ", " << sekizlik << ", "
<< onaltilik << ", " << ikilik << std::endl;
return 0;
}⚠️ Dikkat: Sayının başına yanlışlıkla
0koyarsan, derleyici onu sekizlik (octal) sayı olarak yorumlar.010yazdığında 10 değil 8 elde edersin!
Tip Takma Adları (Type Aliases)
Uzun tip isimlerini kısaltmak için using anahtar kelimesini kullanabilirsin:
#include <iostream>
#include <cstdint>
using Byte = uint8_t;
using Score = int32_t;
using Distance = double;
int main() {
Byte veri = 255;
Score puan = 95;
Distance mesafe = 12.5;
std::cout << "Veri: " << static_cast<int>(veri) << std::endl;
std::cout << "Puan: " << puan << std::endl;
std::cout << "Mesafe: " << mesafe << std::endl;
return 0;
}using ile kodun daha okunabilir hale gelir. Eski C tarzı typedef da çalışır ama modern C++'ta using tercih edilir.
Özet
int günlük tam sayı işleri için varsayılan tercihtir;
long longçok büyük sayılar içindirdouble ondalıklı sayılar için varsayılandır;
floatsadece bellek/performans kritik durumlarda kullanılırchar tek bir karakter tutar ve aslında bir sayıdır (ASCII değeri)
bool sadece
trueveyafalsealır; koşullarda vazgeçilmezdirsizeof() herhangi bir tipin veya değişkenin byte cinsinden boyutunu verir
unsigned sadece pozitif değer tutar ama taşma riski taşır — emin değilsen
signedkullan
AI Asistan
Sorularını yanıtlamaya hazır