C Proje Dosyalarının Organizasyonu

organizasyon

C programlama dilini kullanarak proje geliştiriyor isek ve proje dosyalarımız birden fazla olmaya başladığında, artık bu dosyaları iyi bir şekilde organize etmekten şüphesiz fayda göreceğiz.

C programlama dilini kullanıyoruz ancak proje dosyalarımızın organizasyonunu ne kadar iyi sağlayabiliyoruz? Bu yazıda bazı püf noktaları ile daha organizasyonlu projeler geliştirebilmekten bahsedeceğim.

 1.BÖLÜM

Genelde, C kütüphaneleri karşımıza .c ve .h uzantılı dosyalar şeklinde çıkmaktalar (isim.c ve isim.h gibi). Bir çok program geliştirme arayüzü (IDE) bu standardı kabul etmektedir. Örnek olarak, IDE üzerinde bulunan bir buton sayesinde, o an aktif olan pencere isim.c ise, bahsi geçen özel butona tıklandığında arayüz, isim.c nin bulunduğu klasör içerisinde isim.h dosyasını arar ve bulduğunda açar. Böylece kullanıcı, kütüphanenin header dosyasını aramasına gerek kalmaz.

Öncelikle, header yani başlık anlamına gelen bu deyim .c uzantılı dosyalarının ilk kısımlarına yazılması istenen yada yazılması gereken kısımlardır. Header lar .h uzantılı dosyalarda ayrıca saklanabilir. Bu dosyanın uzantısı .h olmak zorunda değildir ancak yine bu standartlar arasında olan bir kuraldır.

Header dosyalarında, kütüphaneye dair; fonksiyon prototipleri, global değişkenler, #define direktifleri, #include direktifleri, typedef değişken tanımlamaları saklanabilmektedir. Organizasyonu kolay bir kütüphane elde etmek için göz önünde bulundurulması gereken temel kural ise, header dosyasının, projede derlenecek birden fazla .c uzantılı dosya içerisinde, aynı anda kullanılabilir olmasıdır. Diğer bir deyişle, header dosyalarının bir proje içerisinde birden fazla kez tanımlanması problem oluşturmamalıdır. 1. bölümde ağırlıklı olarak bu konuya değinmeye çalışacağım.

C kütüphanelerini .c ve .h uzantılı dosyalar şeklinde saklamanın, .c dosyalarının daha sade bir görünümde olmasının sağlanmasının yanı sıra bazen bu kaçınılmaz bir durum olmaktadır. İlerleyen kısımlarda bunun sebeplerine değineceğim.

fust_falt_2

Fonksiyon prototiplerini, kütüphane içerisinde tekrar yazmamızın önemi; birçoğumuzun bildiği gibi, C derleyicileri derleme işlemini yukarıdan aşağıya doğru ilerleyerek sağlamaktadır ve daha altta yazılmış bir fonksiyonu daha yukarıda bulunan başka bir fonksiyon içerisinde çağrılmak istendiğinde derleme işlemi esnasında, altta ki fonksiyonun bulunamadığına dair bir hata verebilir. Bu sebeple .c dosyalarının en üst bölgelerine resimde de görüldüğü gibi bir fonksiyon prototipi eklenmesi gerekir.

c_proje_dosyalarinin_organizasyonu_3

Kütüphanelerin .c dosyaları içerisindeki bir fonksiyonun, farklı kütüphaneler içerisinde kullanılması istendiğinde ise, kullanıcı .c dosyaları içerisinde, kullanılacak olan fonksiyonun prototipini tek tek yazması gerekir. Bunun yerine, yukarıda ki resimde de görüldüğü gibi, kullanılacak kütüphanenin tüm fonksiyon prototiplerinin saklandığı header dosyası sadece tek satırda #include işlemi ile, ilgili .c dosyasına dahil edilmiş olunur.

c_proje_dosyalarinin_organizasyonu_4

Yukarıda ki resimde projeye dahil edilmiş 3 adet .c dosyası görülmekte. Derleyicinin bu dosyaları nasıl görüntülediği ise hemen sağ tarafta görülebiliyor. Bu kullanım şeklinde dikkat edilmesi gereken nokta; user.c içerisinde, kutuphane.c içinde tanımlanmış fonksiyon kullanıldı ancak kutuphane.h dosyası user.c ile direkt olarak ilişkilendirilmedi. Çünkü comm.h dosyası user.h içerisinde dahil edilmişti ve comm.h içerisindede kutuphane.h dahil edili idi. Dolaylı olarak user.c dosyası içerisinde de kutuphane.h dosyası dahil edilmiş olundu.

Eğer user.h içerisinde de kutuphane.h dahil etme işlemi yapılsaydı aynı header iki kez alt alta yazılmış olunurdu ve bu istenmeyen bir durumdur. Görüldüğü gibi zahmetli bir yöntem ve bir süre sonra takibi zorlaşacağı için genelde daha farklı kullanım şekilleri tercih ediliyor. Bu yazıda iki farklı yöntemden daha bahsedeceğim.

c_proje_dosyalarinin_organizasyonu_5

Yukarıda ki örnekte #include işlemleri sadece .c dosyaları içerisinde yapılıyor. Böylece hangi .c dosyasında başka hangi kütüphanelerin kullanıldığına dair sürekli takip etme yükünden kurtuluruz. Bu sefer de .c uzantılı dosyaları kütüphane ekledikçe kalabalık gözükebilir. Bunun yanısıra, kullanılacak alt kütüphane tanımlamaları, kullanıcı kütüphanesinin .h dosyasında kullanılmak istenebilir. Bu durumda include işlemi .h dosyası içerisinde yapılması istenebilir. Genelde bu durumlar göz ardı edilebilir ancak bir yöntemden daha bahsedeceğim.

c_proje_dosyalarinin_organizasyonu_6

Header dosyaları kutuphane.h deki gibi kapsül içerisine aldığındığı taktirde, programcı takip konusunda dahada özgür olabilir. Çünkü, yukarıda ki görselde kutuphane.c de görüldüğü gibi .h dosyası iki kez #include şeklinde dahil edilse bile ilk dahil etme işleminden sonra ki dahil etme eylemleri otomatik geçersiz kalacaktır.

Ara görünümü özetleyecek olursam; ilk olarak mevcut .c dosyası içinde KUTUPHANE_H adında bir tanımlama olup olmadığını sorgular. Eğer tanımlı değilse ikinci adım olarak KUTUPHANE_H adını tanımlar ve asıl başlık kısımları aktif olur. Kütüphanenin .c dosyası içerisinde ikinci kez KUTUPHANE_H adı sorgulandığında bu ad, .c dosyası üzerinde daha önce tanımlanmış olduğu için, aynı .h dosyası, .c dosyası üzerinde ikinci kez  aktif olmayacaktır. Sonuç olarak biz birden fazla dahil etme işlemi yaptık ancak, sadece bunlardan ilk olanı bu dosya için aktif olabildi.

Tüm header dosyaları bu şekilde kapsül içerisine alındığında, ilk örnekte bahsi geçen problem bu kapsül uygulaması sayesinde, artık problem olmaktan çıkacaktır. İstenilen her dosya içerisinde (.c veya .h) gönül rahatlığıyla kapsüllü başlık dosyaları dahil edilebilir, çünkü bilinir ki her .c dosyasında bu başlık dosyaları en fazla 1 kez aktif olabilecektir.

2.BÖLÜM

c_proje_dosyalarinin_organizasyonu_7

IDE üzerinden projeye .c dosyaları dahil edildiği zaman derleme işlemi esnasında bu .c dosyaları tek tek kendi aralarında derlenir daha sonra link işlemi yapılarak ortaya tek bir executive yada hex dosyası çıkar. Buraya kadar yapılan örnekler de, yukarıda ki görselin sol tarafında ki gibi, tüm .c dosyaları IDE üzerinden projeye dahil edilmiştir.

Konunun diğer bir alt başlığı olarak, .c dosyalarını #include şeklinde başka .c dosyalarına dahil etmek olarak ele alabiliriz.

Genelde bu tercih edilmeyen yöntemler arasında tutulur. Çünkü .c dosyalarında fonksiyonları saklarız. Bir proje içerisinde bir fonksiyon ismi en fazla 1 kez tanımlanabilir. Örnek olarak; Eğer iki adet .c dosyası ile çalışıyor isek ve başka bir kütüphanenin (3. olarak) .c dosyasını bu iki farklı .c dosyasına aynı anda dahil etmeye kalktığımız zaman aynı fonksiyonu, 2 kez tanımlamaya çalışmış oluruz. Bu tanımlama işlemi, her dosyada 1 kez olsa bile dosya sayısı 2 olduğu için projede toplam 2 kez tanımlama eylemi olacaktır ve hatalı işlem yapılmış olunacaktır.

Peki .c dosyalarımızı kapsül içerisine alsak bu durumun önüne otomatik olarak geçebilir miyiz? Hayır geçemeyiz. Çünkü kapsül koruması sadece ilgili dosya içerisinde geçerli olur. Birden fazla .c dosyasında yine aktif olabilir. Dolayısı ile aynı fonksiyonları proje içerisinde yine defalarca tanımlamış olabiliriz.

Peki, kontrolü elden kaçırmadan .c dosyalarını #include ile projeye dahil etme eylemi ne zaman mantıklı tercih olabilir? Bazı kurallar şeklinde listelemek istersek;

  • Projeye dahil edilmesi istenen kütüphanelerin .c dosyaları, sadece main fonksiyonunun bulunduğu .c dosyası içerisine,  bir defalığına #include ile dahil edilir.
  • Her kütüphanenin .h dosyaları, ilgili kütüphanenin .c dosyası içerisine dahil edilmiş olmalıdır.
  • Her kütüphanenin .h dosyaları kapsül korumasına sahip olmalıdır.
  • #include ile main.c dosyasına dahil edilen .c dosyaları, IDE üzerinden tekrar dahil edilmemelidir.
  • Bir .c dosyası ne şekilde olursa olsun projeye en fazla yalnızca bir kez dahil edilmelidir.

Tüm bu şartlara uyarak c projesinde yine iyi bir organizasyon sağlanabilir. Birden fazla .c dosyası ile çalışmış olsak dahi, sonuç olarak sadece tek bir .c dosyası derleyiciye girmiş olur ve çıkışında yine bir adet executive yada hex elde edilebilir. Bu çalışma biçimi ise, yukarıda ki görselde sağ tarafta ifade edilmiştir.

3.BÖLÜM

C proje organizasyonu konusunda değinebileceğim başka bir nokta ise, proje dosyalarını saklama ve dosyalara erişim olacaktır.

Oluşturulacak kütüphane dosyalarının IDE dosyaları ile karışmaması için ayrı bir klasör (Örn. source) içerisinde saklanması ile daha düzenli ve erişilmesi kolay bir yapı elde edilebilinir. Aynı zamanda, bir kütüphanenin .c ve .h dosyalarının aynı klasör içerisinde bulunması ile IDE in de sağlamış olduğu bazı kolaylıklardan faydalanılabilinir.

Projede kullanılacak kütüphanelerin bulunduğu klasörleri projeye dahil etmek, bazı avantajlar sağlamaktadır. Her seferinde dosya yolunu uzunca yazıp dosyaya erişmek yerine, dosyaların bulunduğu klasörlerin yolları projeye dahil edilebilinir. Böylece artık sadece #include “isim.h” yazarak ilgili klasörde bulunan isim.h dosyasına erişilebilinir.

Derleyici tarafından bazı hazır dosya yolları daha önceden tanımlanmıştır. Bu sayede hiç bir dosya yolu dahil etme işlemi yapılmadan da, bir çok derleyicide hali hazırda bulunan, derleyici sağlayıcısı tarafından desteklenmiş bazı standart kütüphanelere (Örn. #include<stdio.h> ) erişilebilinir.

Dosya yolu dahil etme işlemi, IDE üzerinde derleyici için ayrılmış ayar bölümlerinde, “include directories” gibi isimler ile belirtilen bölümler üzerinden yapılabilmektedir. Genelde, yine bir butona tıklamak suretiyle açılan, dosya yolu bulmamıza yardımcı olacak pencere üzerinden, ilgili klasör bulunup seçilerek onaylanır, böylece dahil etme işlemi tamamlanmış olunur.

Projeye dahil edilen klasörlerin dosya yolları, proje dosyasında kaydı tutulmaktadır. Bu sebeple örnek bir projenin, kaynak dosyalarına sahip olsak bile, yeni bir proje dosyası oluşturup sadece kaynak dosyalarını dahil etmek, projeyi derleyebilmemiz için yeterli olmayabilir. Bu anlamda ilgili dosya yollarının da dahil edilmesi gerekebilir. Bu durumda derleyici, ilgili dosyalarının bulunamadığına dair hata verecektir.

Yazımı sonuna kadar sabırla okuduğunuz için teşekkür ederim.

“C Proje Dosyalarının Organizasyonu” için 4 yorum

  1. Güzel bir yazı olmuş,
    uzun soluklu, ellerine sağlık.

    Bir sorum olacak,
    değinmekte fayda var bence;
    örneğin;
    #include “bir.h”
    ile
    #include
    farkı nedir?

    1. Güzel dileklerin için teşekkür ederim. 3. bölümün 3 ve 4 üncü paragraflarında vermiş olduğum örnekler bu soruna yüzeysel de olsa bir cevap niteliğinde. Tekrar belirtmem gerekirse; esasında iki kullanım şekli de ufak bir fark dışında aynı işi yapar bu ufak fark ise;

      Tırnak içerisinde belirtilen dosya ismi, önişlem derlemesi esnasında ilk olarak kullanıcının tanımladığı dosya yollarında aranır bulunursa kullanılır bulunamaz ise derleyicinin sabit tanımlamış olduğu dosya yollarında aranır bulunursa kullanılır bulunamazsa derleyici hata verir.

      Tam tersinde ise, yani büyüktür küçüktür karakterleri ile belirtilen dosya ismi şeklinde ki kullanımında ise tam tersi durum geçerlidir. Yani ilgili dosya önce, derleyicinin tanımlamış olduğu dosya yollarında aranır sonra kullanıcının tanımlamış olduğu dosya yolları içerisine bakılır.

      Özetle, dosya yolları arasında, derleyici tarafından bakılma önceliğini belirlemeye yarar. Peki neden ihtiyaç duyulabilir? Örnek olarak kullanıcı derleyicinin sağladığı stdio.h dosyasına alternatif aynı isimde bir dosya oluşturdu ve kendi kullanıcı klasörlerinde sakladı. Artık, projede aynı isimde bulunan birden fazla dosyaya erişilebilinir. Aynı proje içerisinde bazı .c dosyalarında sabit kütüphaneyi, bazı .c dosyalarında ise kendi yazmış olduğu kütüphaneye sadece bu ufak farktan yararlanarak erişebilir.

Bir Cevap Yazın

Or

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir