C++ Adres ve Bellek Kavramı
C++’ta adres ve bellek kavramlarını öğrenin. Bellek yapısı, değişken adresleri ve veri saklama mantığı örneklerle anlatılıyor.
C++ dilinde veriler bilgisayarın belleğinde (memory) saklanır. Her değişkenin bellekte kendine ait bir adres (address) konumu vardır. Bellek adreslerini bilmek, pointer (gösterici) gibi güçlü C++ özelliklerini anlamanın temelidir. Bu makalede bellek yapısını, adres kavramını ve değişkenlerin bellekte nasıl tutulduğunu öğreneceğiz.
1. Bellek Nedir?
Bellek (RAM), program çalışırken verilerin ve komutların geçici olarak saklandığı alandır. Program kapandığında bellekteki veriler silinir. C++ derleyicisi değişkenler için bellekten yer ayırır ve bu alanlara adres atar.
Örnek olarak, aşağıdaki kodda her değişkenin bellekte bir adresi vardır:
#include <iostream>
using namespace std;
int main() {
int yas = 25;
double pi = 3.14;
cout << "yas değişkeninin adresi: " << &yas << endl;
cout << "pi değişkeninin adresi: " << &pi << endl;
return 0;
}
Çıktı örneği:
yas değişkeninin adresi: 0x61ff0c
pi değişkeninin adresi: 0x61ff08
Her adres, bellekteki fiziksel bir konumu temsil eder ve genellikle **16’lık (hexadecimal)** formatta gösterilir.
2. & (Adres) Operatörü
& operatörü, bir değişkenin adresini verir.
Yani değişkenin değerinin bulunduğu bellek konumunu öğrenmemizi sağlar.
int sayi = 100;
cout << "sayi'nin adresi: " << &sayi << endl;
cout << "sayi'nin değeri: " << sayi << endl;
Adres bir konumdur, değer ise o konumda saklanan veridir. Bu ayrım pointer kavramını anlamanın temelidir.
3. Bellek Yapısı (Stack ve Heap)
Bir C++ programı çalıştığında bellek genel olarak iki ana bölgeye ayrılır:
| Bölge | Açıklama | Kullanım |
|---|---|---|
| Stack | Otomatik (yerel) değişkenleri tutar. Bellek, bir fonksiyon çağrıldığında ayrılır ve fonksiyon sona erdiğinde otomatik olarak serbest bırakılır. | Otomatik ömürlü değişkenler (int, double vb.) |
| Heap | Dinamik olarak ayrılan bellek için kullanılır. new ve delete ile manuel olarak yönetilir. |
Dinamik veri yapıları (new ile oluşturulan nesneler) |
Performans Notu: Stack son derece hızlıdır çünkü bellek ayırmak yalnızca dahili bir işaretçinin yerini değiştirmek kadar basittir. Heap ise işletim sisteminin istenen boyuta uygun boş bir bellek bloğu bulup ayırmasını gerektirdiğinden daha yavaştır.
Örnek:
int x = 10; // Stack üzerinde tutulur (hızlı ve otomatik)
int *p = new int(5); // Heap üzerinde tutulur (daha yavaş, manuel temizleme gerekir)
Dikkat edilmesi gereken nokta, p işaretçisinin kendisinin Stack üzerinde bulunması,
işaret ettiği değerin ise Heap üzerinde olmasıdır.
Bu ayrımı anlamak memory leak (bellek sızıntısı) problemlerini önlemek açısından önemlidir.
4. sizeof Operatörü
sizeof operatörü, bir değişkenin veya veri türünün bellekte kaç byte yer kapladığını döndürür.
#include <iostream>
using namespace std;
int main() {
cout << "int boyutu: " << sizeof(int) << " byte" << endl;
cout << "double boyutu: " << sizeof(double) << " byte" << endl;
cout << "char boyutu: " << sizeof(char) << " byte" << endl;
return 0;
}
Tipik bir sistemde bu değerler şu şekildedir:
int→ 4 bytedouble→ 8 bytechar→ 1 byte
5. Bellekte Değişkenlerin Görselleştirilmesi
Örneğin aşağıdaki kodu ele alalım:
int a = 5;
int b = 10;
Bellekte şu şekilde temsil edilir:
Adres Değer
0x61ff0c → 5 (a)
0x61ff08 → 10 (b)
Her değişkenin adresi farklıdır. Bu adresler bellek sırasına göre artabilir veya azalabilir.
6. Pointer (Gösterici) Kavramına Giriş
Pointer, başka bir değişkenin adresini saklayan özel bir değişkendir.
Pointer tanımlamak için * (yıldız) operatörü kullanılır.
#include <iostream>
using namespace std;
int main() {
int sayi = 42;
int *ptr = &sayi; // sayi'nin adresi pointer'a atanır
cout << "sayi değeri: " << sayi << endl;
cout << "ptr'nin gösterdiği değer: " << *ptr << endl;
cout << "ptr'nin adresi: " << ptr << endl;
return 0;
}
&→ adres operatörüdür (değişkenin adresini verir)*→ pointer’ın işaret ettiği değere erişir (dereference işlemi)
Bu örnekte ptr değişkeni bellekteki sayi değişkeninin adresini tutar.
*ptr yazıldığında, bu adresin içindeki değere erişilir.
7. Null Pointer ve Güvenli Kullanım
Pointer’lar yanlış adresleri göstermemelidir.
Eğer henüz bir adrese atanmadıysa nullptr değeri verilmelidir.
int *p = nullptr;
if (p == nullptr) {
cout << "Pointer şu anda hiçbir adresi göstermiyor." << endl;
}
Bu kontrol, runtime hatalarını ve çökme (segmentation fault) sorunlarını önler.
8. Pointer ve Bellek Diyagramı
Aşağıdaki örneği inceleyelim:
int x = 10;
int *p = &x;
Bellek görünümü:
Değişken | Adres | Değer
x | 0x61ff0c | 10
p | 0x61ff08 | 0x61ff0c
p pointer’ı x’in adresini tutar.
*p kullanarak x’in değerine erişebiliriz.
9. Bellek Yönetimi ve Güvenlik
C++'ta doğrudan bellek yönetimi büyük bir esneklik sunar, ancak aynı zamanda önemli bir sorumluluk da getirir. Dinamik olarak ayrılan her bellek alanı delete ile serbest bırakılmalıdır.
int *p = new int(100); // Heap üzerinde bellek ayır
cout << *p << endl;
delete p; // Belleği serbest bırak
p = nullptr; // Dangling pointer oluşmasını önle
Bellek sızıntısı (memory leak), ayrılan belleğin uygun şekilde serbest bırakılmaması durumunda oluşur.
Bu durum zamanla programın daha fazla bellek tüketmesine ve performansının düşmesine neden olabilir.
Bunu önlemek için her new ifadesi bir delete ile eşleştirilmelidir.
Ham işaretçileri (raw pointers) ve manuel bellek yönetimini anlamak C++ öğrenmek açısından önemlidir.
Ancak Modern C++ (C++11 ve sonrası), üretim kodunda bunların doğrudan kullanılmasını önermez.
Bunun yerine standart kütüphane, <memory> başlığı altında bulunan
Smart Pointer'ları (örneğin std::unique_ptr ve
std::shared_ptr) sunar. Bunlar belleği otomatik olarak yöneterek
bellek sızıntıları ve dangling pointer problemlerini büyük ölçüde ortadan kaldırır.
10. TL;DR
- Her değişken bellekte bir adrese sahiptir (
&operatörüyle alınır). - Stack → otomatik, Heap → dinamik bellek alanıdır.
sizeofile türlerin kapladığı alan ölçülebilir.int *p→ pointer tanımlar,*p→ değere erişir.nullptr→ güvenli başlangıç değeri olarak kullanılmalıdır.newile ayrılan bellek,deleteile serbest bırakılmalıdır.- Tüm örnekler Visual Studio 2022 veya GCC 11+ derleyicilerinde çalıştırılabilir.