C dilinde makro ön işleyicileri, kaynak kodunun taşınabilirliğini, okunabilirliğini ve kolay ayarlanabilirliğini sağlamak için dilin bir parçası olarak ortaya çıkmıştır. #define, #ifdef, #ifndef direktifleri aracılığıyla koşullu kod bölümleri oluşturabilir, sabitler ilan edebilir ve harici dosyaları (#include) bağlayabilirsiniz.
Meselenin Tarihi:
Ön işleyici direktifleri, kaynak kodunu farklı sistemlere ve derleyicilere uyarlamayı basitleştirmek ve tekrarlayan işlemleri otomatikleştirmek için uygulamaya konmuştur.
Problem:
Ön işleyici olmadan platform farklılıklarından soyutlanmak, kod parçalarını tekrarlamak ve başlık dosyalarının çift bağlantısını önlemek mümkün olmuyordu. Ayrıca, dikkatli olmak gerekiyor çünkü makrolar tip kontrolüne tabi değildir ve kapsamları yoktur.
Çözüm:
Sabitleri, inline fonksiyonları ilan etmek, koşullu derleme yapmak ve başlık dosyalarının çoklu dahil edilmesini önlemek için makro ön işleyicilerin kullanımı.
Kod örneği:
#ifndef MY_HEADER_H #define MY_HEADER_H #define MAX_SIZE 100 #ifdef DEBUG #define LOG(x) printf("%s\n", x) #else #define LOG(x) #endif #endif /* MY_HEADER_H */
Ana Özellikler:
Başlık dosyasında include guard'ı unutursanız ne olur?
Başlık dosyası bir .c dosyasına birkaç kez dahil edilebilir (başka .h dosyaları aracılığıyla) bu da yeniden tanımlama hatalarına (redefinition) yol açar.
#define makrosunun inline-fonksiyon tanımından farkı nedir?
#define sadece metni değiştirdiği için tipleri ve sözdizimi doğruluğunu kontrol etmezken, inline-fonksiyon normal bir fonksiyondur ve tip analizi aşamasında derleyici tarafından kontrol edilir.
Makrolar yan etkiler içerebilir mi?
Evet, eğer makro düzgün tanımlanmadıysa, geçirilen ifadeler birden fazla kez hesaplanabilir. Örneğin:
#define SQUARE(x) (x) * (x) int a = SQUARE(++i); // ++i İKİ KEZ çalıştırılacak!
Yan etkiler yaratan ve parantez içermeyen bir makro kullanımı:
#define DOUBLE(x) x + x int result = DOUBLE(1+2); // sonuç 6 değil, 1+2+1+2=6 mı? Hayır, 1+2+1+2=6 — öyle mi? Hayır, 1+2+1+2 olacaktır. // Ama gerçekte bu 1 + 2 + 1 + 2 = 6 olacak, ama eğer DOUBLE(++i) yaparsanız, ++i iki kez uygulanacak.
Artılar:
Eksikler:
Parantezli bir makro tanımı yapma ve basit sabitler için kullanma:
#define DOUBLE(x) ((x) + (x)) #define BUFFER_SIZE 1024
Artılar:
Eksikler: