Bölüm 2: Diziler ve Yapılar
Çoktan Seçmeli · Dizi ADT
Soru 1: İşaretçiyle İndis
int a[8]; int *p = a + 2; tanımlarından sonra p[3] ve *(p - 1) hangi öğelerdir?
C: p, a[2]'yi gösterir. p[3] ≡ *(p + 3) ≡ a[2 + 3] = a[5]; *(p - 1) = a[1]. İşaretçi aritmetiği öğe sayar: p + 3, 3·sizeof(int) bayt ileridedir. A ve D, p'nin a'nın başını gösterdiğini varsayar.
Çoktan Seçmeli · Dizi ADT
Soru 2: Parametrede sizeof
int 4 bayt, işaretçi 8 bayt olan bir sistemde program ne yazdırır?
void f(int a[]) { printf("%zu\n", sizeof a / sizeof a[0]); } int main(void) { int d[10]; printf("%zu ", sizeof d / sizeof d[0]); f(d); return 0; }
B: main'de d gerçek bir dizidir: 40 / 4 = 10. Parametredeki int a[] ise int *a ile aynıdır; sizeof a işaretçinin boyutu (8) olur: 8 / 4 = 2. Dizi fonksiyona kopyalanmaz, yalnızca adresi geçer; bu yüzden boyut ayrı bir parametreyle gönderilir. Derleyici de bu satır için uyarı verir.
Çıktı Sorusu · Dizi ADT
Soru 3: İşaretçi Aritmetiği
Parça ne yazdırır? (char *)q - (char *)(d + 1) kaç olurdu (int 4 bayt)?
int d[] = {10, 20, 30, 40, 50}; int *p = d + 1, *q = &d[4]; printf("%td\n", q - p); printf("%d\n", *p + 1); printf("%d\n", *(p + 1)); p += 2; *p = 7; printf("%d %d\n", d[3], p[-1]);
Cevabı göster
3 21 30 7 30
q - p: d[4] ile d[1] arasında 3 öğe (bayt değil).*p + 1: önce*p= 20, sonra + 1 → 21.*(p + 1)ise d[2] = 30'dur; parantez önceliği değiştirir.p += 2→ p = &d[3];*p = 7d[3]'ü değiştirir.p[-1]= d[2] = 30.
Bayt farkı 3 · 4 = 12'dir: char * aritmetiği bayt sayar.
Çoktan Seçmeli · Dinamik Diziler
Soru 4: realloc ile Büyütmek
n öğeli dinamik dizi a, m > n öğeye büyütülecek. Hangisi hem eski öğeleri korur hem de bellek ayrılamazsa eski bloğu kaybetmez?
B: realloc başarısız olursa NULL döner ve eski blok yerinde kalır; sonuç önce geçici değişkene alınmalıdır. A'da NULL a'nın üzerine yazılır, eski blok sızar. C eski öğeleri kopyalamaz ve eski bloğu bırakmaz; D eski verileri yok eder.
Adım Adım Çalıştırma · Dinamik Diziler
Soru 5: Sabit Artışla Büyüyen Dizi
ekle kapasiteyi ikiye katlamak yerine 2 artırıyor. Boş diziye 6 öğe eklenince kaç kopya yapılır? n eklemede maliyet nasıl büyür?
Boş dizi {NULL, 0, 0}. Sırayla 6, 1, 8, 3, 5, 2 eklenecek.
Dolu (0 == 0): kap 0 → 2. NULL'dan realloc, malloc gibi davranır. 6 yazılır.
Yer var: 1 doğrudan yazılır.
Dolu: kap 2 → 4; realloc eski 2 öğeyi yeni bloğa taşır.
Yer var: 3 yazılır.
Dolu: kap 4 → 6; 4 kopya daha.
6 eklemede 2 + 4 = 6 kopya. Her 2 eklemede bir büyütme: n eklemede ≈ n²/4 kopya (n = 1000 için 249 500) → O(n²); ikiye katlamada 1023'ü geçmez.
int ekle(DinDizi *d, int x) { if (d->boyut == d->kap) { int yeni = d->kap + 2; /* sabit */ int *t = realloc(d->veri, yeni * sizeof *t); if (t == NULL) return 0; d->veri = t; d->kap = yeni; } d->veri[d->boyut++] = x; return 1; }
Hata Bulma · Dinamik Diziler
Soru 6: 2B Diziyi Bırakmak
dizi2b(3, 4) ile ayrılan diziyi bırakan bu fonksiyonun hatası nedir? Doğrusu nasıl yazılır; toplam kaç free gerekir?
void sil2b(int **x, int satir) { int i; free(x); for (i = 0; i < satir; i++) free(x[i]); }
Cevabı göster
free(x) işaretçi dizisini bırakır; ardından x[i] okumak free edilmiş belleğe erişimdir (tanımsız davranış). Program çoğu zaman çalışıyor gibi görünür; bu hatayı daha sinsi yapar.
void sil2b(int **x, int satir) { int i; for (i = 0; i < satir; i++) free(x[i]); /* once satirlar */ free(x); /* sonra dizi */ }
dizi2b(3, 4) 1 + 3 = 4 malloc yapar; 4 free gerekir (sayaçla doğrulandı). Yalnız free(x) yazılsaydı satırlar sızardı.
Çoktan Seçmeli · Çok Boyutlu Diziler
Soru 7: Sütun Öncelikli Adres
float m[6][5] dizisi α = 1000 adresinden başlıyor, sizeof(float) = 4. Dizi sütun öncelikli saklansaydı &m[2][3] kaç olurdu?
D: Sütun öncelikli düzende öğeden önce 3 tam sütun (3 · 6 = 18 öğe) ve sütununda 2 öğe vardır: 1000 + 20 · 4 = 1080. A satır önceliklidir (C'nin kullandığı): 1000 + (2 · 5 + 3) · 4 = 1052. B, sütun uzunluğu yerine satır uzunluğunu (5) kullanır.
Klasik Soru · Çok Boyutlu Diziler
Soru 8: Horner ile Ofset
char K[4][3][6]; dizisi 500 adresinden başlıyor. K[2][1][4]'ün ofsetini Horner yöntemiyle bulunuz; adresi nedir, kaç çarpma yapılır, hangi boyut hesaba girmez?
Cevabı göster
t = 2 → t = 2 · 3 + 1 = 7 → t = 7 · 6 + 4 = 46. char 1 bayt olduğundan adres 500 + 46 = 546.
n − 1 = 2 çarpma yapılır. İlk boyut (4) formüle hiç girmez; yalnızca sınır denetiminde gerekir. Açık formül de aynıdır: 2 · 3 · 6 + 1 · 6 + 4 = 46. Gerçek C dizisinde &K[2][1][4] - &K[0][0][0] 46 verir.
Çoktan Seçmeli · Üçgen ve Kuşak Matrisler
Soru 9: Üst Üçgen Matris
5 × 5 üst üçgen matrisin (j ≥ i) öğeleri satır öncelikli olarak tek boyutlu bir diziye yazılıyor. a13 bu dizinin kaçıncı indisindedir?
A: 0. satırda 5 öğe (indis 0–4) vardır; 1. satır a11, a12, a13 ile 5, 6, 7'ye yazılır. Formül: i·n − i(i−1)/2 + (j − i) = 5 − 0 + 2 = 7. B alt üçgen formülüdür (i(i+1)/2 + j); C tam matristeki konumdur (i·n + j).
Adım Adım Çalıştırma · Üçgen ve Kuşak Matrisler
Soru 10: Kuşak Matriste Erişim
n = 5, a = 2, b = 3 (köşegen dâhil) kuşak matris KusakMatrisKur ile kuruldu. (3, 2), (1, 3), (2, 2), (0, 4) ve (4, 1) için KusakMatrisEris ne döndürür?
Kuşaklar −1, 0, 1, 2 (uzunluk 4, 5, 4, 3) → 16 öğe, ARA = [0, 4, 9, 13]. Hücrelerdeki sayı kuşak no j − i.
d32: j − i = −1 → alt. i − j = 1 < 2 → ara[−1 + 1] + j = 0 + 2 = 2.
d13: j − i = 2 < b = 3 → üst kuşak: ara[2 + 1] + i = 13 + 1 = 14.
Köşegen de 'alt' dalında: ara[0 + 1] + j = 4 + 2 = 6.
d04: j − i = 4 ≥ b → kuşak dışı, üst sabit bölge: −1.
d41: i − j = 3 ≥ a = 2 → alt sabit bölge: −2. Her çağrı sabit sayıda işlem: O(1).
int KusakMatrisEris(int i, int j, int n, int a, int b, int ara[]) { if (i < 0 || j < 0 || i >= n || j >= n) return -3; else if (j - i >= 1) { /* ust */ if (j - i < b) return ara[j - i + a - 1] + i; else return -1; } else if (i - j < a) /* alt */ return ara[j - i + a - 1] + j; else return -2; }
Çoktan Seçmeli · Üçgen ve Kuşak Matrisler
Soru 11: Kuşaktaki Öğe Sayısı
6 × 6 bir matriste yalnızca ana köşegen ve onun altındaki iki kuşak saklanacak (a = 3, b = 1). Kuşak dizisi kaç öğe tutar?
D: Kuşak uzunlukları 4 + 5 + 6 = 15; formül n(a + b − 1) − a(a − 1)/2 − b(b − 1)/2 = 18 − 3 − 0 = 15. A her kuşağı n uzunlukta sayar; alt kuşaklar köşegenden uzaklaştıkça birer kısalır.
Çoktan Seçmeli · Üçgen ve Kuşak Matrisler
Soru 12: Kısa Devre
a n öğeli bir dizi ve i == n. Aşağıdaki koşullardan hangisi dizinin dışındaki a[n]'yi okur?
C: & bit düzeyi VE'dir; iki işleneni de hesaplanır, kısa devre yapmaz. && ve || ise soldan sağa değerlendirilir: A'da i < n yanlış olunca sağ taraf hiç hesaplanmaz; B'de i >= n doğru olunca durulur. A ile D aynı derecede güvenlidir.
Çıktı Sorusu · Yapılar
Soru 13: Yapı Ataması
Yapı ataması alanları nasıl kopyalar? Parça ne yazdırır?
typedef struct { char ad[8]; int *not; } kayit; int n1 = 70; kayit a = {"Ali", &n1}, b; b = a; strcpy(b.ad, "Can"); *b.not = 90; printf("%s %d\n", a.ad, *a.not);
Cevabı göster
Çıktı: Ali 90.
b = aalan alan kopyalar:addizisinin içeriği b'ye kopyalanır,notişaretçisinin ise yalnızca değeri (adres).strcpy(b.ad, "Can")yalnız b'nin kendi dizisini değiştirir; a.ad "Ali" kalır.a.notveb.notaynın1'i gösterir;*b.not = 90n1'i değiştirir, a'dan da 90 okunur.
Buna sığ kopya denir: işaretçi alanlı yapılarda gösterilen veri paylaşılır. *b.not, *(b.not) demektir; . işleci *'dan önceliklidir.
Çoktan Seçmeli · Yapılar
Soru 14: Hizalama ve sizeof
int 4 bayt ve 4 bayta hizalanıyor. struct { char a; int b; char c; } için sizeof tipik olarak kaçtır?
A: a'dan sonra b'yi 4'ün katına hizalamak için 3 bayt dolgu eklenir (0: a, 4–7: b, 8: c); yapı boyutu da en geniş hizalamanın katı olmalıdır: 9 → 12. C alanların ham toplamıdır. B, alanlar { int b; char a, c; } sırasıyla yazılınca elde edilir (4 + 1 + 1 → 8).
Adım Adım Çalıştırma · Dizgeler
Soru 15: Dizgeyi Ters Çevirmek
tersine fonksiyonu "kalem" dizgesini nasıl değiştirir? Program ne yazdırır?
strlen = 5 → q son harfi gösterir; '\0' yerinde kalmalı.
p < q: 'k' ile 'm' yer değiştirir.
p++, q-- → 1 < 3: 'a' ile 'e' yer değiştirir.
p == q: ortadaki 'l' yerinde kalır, döngü biter.
n/2 takas → O(n). Boş dizgede q = s − 1 olurdu; dizinin öncesini gösteren işaretçi oluşturmak tanımsızdır, önce strlen(s) == 0 denetlenmelidir.
void tersine(char *s) { char *p = s, *q = s + strlen(s) - 1, t; while (p < q) { t = *p; *p = *q; *q = t; p++; q--; } } /* main: */ char s[] = "kalem"; tersine(s); printf("%s\n", s);
Hata Bulma · Dizgeler
Soru 16: Dizge Kopyası
Aşağıdaki kodda üç hata var. Hatalar nelerdir ve doğrusu nasıl yazılır?
char *kopyasi(const char *ad) { char *s = malloc(strlen(ad)); strcpy(s, ad); return s; } /* main: */ char *k = kopyasi("Ali"); if (k == "Ali") printf("ayni\n");
Cevabı göster
malloc(strlen(ad))sonlandırıcı'\0'için yer ayırmaz: "Ali" için 3 bayt ayrılır,strcpy4 bayt yazar → taşma. Doğrusustrlen(ad) + 1.mallocsonucuNULLiçin denetlenmemiş.k == "Ali"içerikleri değil adresleri karşılaştırır; heap'teki kopya hiçbir zaman sabit dizgenin adresinde değildir.strcmp(k, "Ali") == 0yazılmalı.
char *s = malloc(strlen(ad) + 1); if (s == NULL) return NULL; strcpy(s, ad); /* ... */ if (strcmp(k, "Ali") == 0) printf("ayni\n"); free(k);
Kopya iş bitince free edilmelidir.
Kod Yazma · Matris İşlemleri
Soru 17: Düz Dizide Matris Çarpımı
m × n'lik a ile n × p'lik b satır öncelikli olarak tek boyutlu dizilerde tutuluyor. Çarpımı m × p'lik c'ye yazan mult fonksiyonunu yazınız. 3 × 4 ile 4 × 2 çarpımında kaç çarpma yapılır?
Cevabı göster
void mult(const int *a, const int *b, int *c, int m, int n, int p) { int i, j, k; for (i = 0; i < m; i++) for (j = 0; j < p; j++) { int s = 0; for (k = 0; k < n; k++) s += a[i * n + k] * b[k * p + j]; c[i * p + j] = s; } }
aik satır öncelikli düzende a[i * n + k]'dadır (önünde i tam satır). c'nin m·p hücresinin her biri n çarpım ister: 3 · 4 · 2 = 24 çarpma, 6 hücre → O(m·n·p); kare matriste O(n³).