C dilinde diziler, tek bir türden sıralı bir dizi öğe saklamak için temel bir yapıdır. Diziler, indeks ile hızlı erişim sağlar ve işaretçilerle yakından ilişkilidir. Diziler statik, otomatik (yığın üzerinde) veya dinamik (yığın dışında) olarak tanımlanabilir. Tahsis türü, dizinin yaşam süresini, kodun farklı bölgelerinden erişilebilirliğini ve bellek yönetimi gereksinimlerini etkiler.
Sorunun Tarihi
İlk C, yalnızca statik ve otomatik diziler tanımlamaya izin veriyordu, ancak dinamik bellek tahsisi (malloc, calloc, free işlevleri) ile birlikte, kodun esnekliğini artıran yeni tasarım kalıpları ortaya çıktı.
Sorun
Geliştiriciler genellikle boyutlar, yaşam süreleri ve dizilerin temizlenmesi konusunda hata yapar, bu da bellek sızıntılarına, yarış koşullarına ve bellek hasarına yol açar.
Çözüm
Göreve göre depolama türünü dikkatlice seçmek, başlatmayı dikkatlice izlemek ve dinamik diziler için bellek tahsisini zamanında serbest bırakmak.
Kod Örneği:
#include <stdio.h> #include <stdlib.h> int main() { // Otomatik (yığın üzerinde) int auto_arr[5] = {1,2,3,4,5}; // Statik (program çalıştığı sürece var) static int static_arr[5]; // Dinamik (yığın dışında) int *dyn_arr = malloc(5 * sizeof(int)); for (int i = 0; i < 5; i++) dyn_arr[i] = i * 2; // Kullanım for (int i = 0; i < 5; i++) printf("%d ", dyn_arr[i]); printf(" "); free(dyn_arr); return 0; }
Anahtar Özellikler:
Dinamik bir dizinin boyutunu sizeof ile öğrenebilir miyiz?
Hayır, sizeof(ptr) dinamik dizi için göstericinin boyutunu döner, dizinin boyutunu döndürmez. Boyutu manuel olarak saklamak veya ayrı bir değişken kullanmak gereklidir.
int* arr = malloc(10 * sizeof(int)); printf("%zu ", sizeof(arr)); // Göstericinin boyutu, dizinin değil
Dizinin sınırlarını aşarsak ne olur?
C dilinde dizinin sınır kontrolü otomatik olarak yapılmaz: sınırların dışında erişim, undefined behavior (tanımsız davranış) ile sonuçlanır. Hatalar yalnızca çalışma aşamasında tespit edilir veya hiç tespit edilmez.
Bir yerel (otomatik) diziyi fonksiyondan geri döndürebilir miyiz?
Hayır! Fonksiyon içinde tanımlanan bir dizi, fonksiyon tamamlandığında silinir. Böyle bir diziyi döndürmek, zaten serbest bırakılmış bir belleğe erişimle sonuçlanır.
int* create_wrong_array() { int arr[10]; return arr; // Hata: yığından bir gösterici döndürme }
Geliştirici, yığın üzerinde bir dizi oluşturur ve işlevden ona gösterici döndürür. Program bazen çökebilir veya çöp döndürebilir.
Artılar:
Eksiler:
Dinamik tahsis kullanımı, boyutu gösterici ile birlikte geçirme, bellek temizliği için free ile. Bellek serbest bıraktaki tüm durumlar unit testler ile kontrol edilir.
Artılar:
Eksiler: