Makro kavramını iyi anlamıyorum. Makro nedir? İşlevden nasıl farklı olduğunu anlamıyorum? Hem işlev hem de makro bir kod bloğu içerir. Peki makro ve fonksiyon arasındaki fark nedir?
Makro kavramını iyi anlamıyorum. Makro nedir? İşlevden nasıl farklı olduğunu anlamıyorum? Hem işlev hem de makro bir kod bloğu içerir. Peki makro ve fonksiyon arasındaki fark nedir?
Yanıtlar:
Bu cevabın polarize edici oylama şeklini gözlemledikten sonra aşağıdaki açıklamayı eklemek istiyorum.
Cevap teknik doğruluk ve geniş genelleme göz önünde bulundurularak yazılmadı. Tam veya doğru olmaya çalışmadan basit bir dilde, makrolar ve fonksiyonlar arasındaki farkı bir programlama acemi için açıklamak alçakgönüllü bir girişimdi (aslında doğru olmaktan çok uzaktır). Cevabı hazırlarken C programlama dili aklımdaydı, ama açık bir şekilde bahsetmediğim ve herhangi bir (potansiyel) karışıklığa neden olduğum için özür dilerim.
Jörg W Mittag'in paylaştığı yanıtı gerçekten dikkate alıyorum . Okumak için kavrayıcıydı (daha az biliyorum) ve gönderildikten kısa bir süre sonra iptal ettim. Yazılım Mühendisliği Yığın Değişimi'ne yeni başladım ve şu ana kadarki deneyim ve tartışmalar gerçekten içgörü kazandı.
Bu yanıtı burada bırakacağım, çünkü diğer yazılım geliştirme yeni başlayanlar için yararlı olabilir, teknik doğruluklara girmeden bir kavramı anlamaya çalışıyorum.
Hem makro hem de işlev bağımsız kod birimini temsil eder. Her ikisi de bir programın modüler tasarımına yardımcı olan bir araçtır. Kaynak kodunu yazan programcı açısından oldukça benzer görünüyorlar. Ancak, program yürütme yaşam döngüsü boyunca nasıl ele alındıklarında farklılık gösterirler.
Makro bir kez tanımlanır ve bir programdaki birçok yerde kullanılır. Makro, ön işleme aşamasında satır içi olarak genişletilir. Böylece, kaynak kodu derlendikten sonra teknik olarak ayrı bir varlık olarak kalmaz. Makro tanımındaki ifadeler, tıpkı diğer ifadeler gibi program talimatlarının bir parçası haline gelir.
Makro yazmanın arkasındaki sebep, kaynak kodun yazılmasını ve yönetilmesini programcı için kolaylaştırmaktır. Makrolar genellikle tam teşekküllü bir işlev yazmanın performans ek yükü / çalışma zamanı cezası olacağı daha basit görevler için istenir. Bir makronun işlev yerine tercih edilebilir olduğu durumlara örnekler:
Sabit değerleri (matematiksel veya bilimsel değerler gibi) veya programa özgü bazı parametreleri kullanma.
Günlük mesajlarını yazdırma veya iddiaları işleme.
Basit hesaplamalar veya durum kontrolleri yapmak.
Makro kullanırken, makroda programın kullanıldığı her yerde anında kullanılabilen tek bir yerde değişiklik / düzeltme yapmak kolaydır. Değişikliklerin etkili olması için programın basit bir şekilde yeniden derlenmesi gerekir.
Diğer yandan fonksiyon kodu, program içinde ayrı bir birim olarak derlenir ve programın yürütülmesi sırasında sadece gerektiğinde belleğe yüklenir. İşlev kodu programın geri kalanından bağımsız kimliğini korur. İşlev birden çok kez çağrılırsa yüklenen kod yeniden kullanılır. Çalışan programda işlev çağrısı ile karşılaşıldığında, kontrol çalışma zamanı alt sistemi tarafından ona aktarılır ve çalışan programın içeriği (iade talimatı adresi) korunur.
Bununla birlikte, bir işlevi çağırırken karşılaşılması gereken hafif bir performans cezası vardır (bağlam değiştirme, ana program talimatlarının dönüş adresini koruma, parametreleri geçirme ve dönüş değerlerini işleme vb.). Bu nedenle, fonksiyonun kullanımı sadece karmaşık kod blokları için (daha basit durumları işleyen makrolara karşı) istenir.
Tecrübe ile, bir programcı bir kod parçasının genel program mimarisinde bir makro ya da fonksiyon olarak iyi bir uyum olup olmayacağına karar verir.
Ne yazık ki, programlamada "makro" teriminin birçok farklı kullanımı vardır.
Lisp dil ailesinden ve onlardan esinlenilen dillerin yanı sıra Scala ve Haskell gibi birçok modern fonksiyonel veya işlevsel ilham veren dilde ve Boo gibi bazı zorunlu dillerde, makro derleme zamanında çalışan bir kod parçasıdır (veya en azından derleyici olmayan uygulamalar için çalışma zamanından önce) ve Özet Sözdizimi Ağacı'nı (veya belirli bir dildeki eşdeğeri, örneğin Lisp'de, S-İfadeleri olurdu) derleme sırasında başka bir şeye dönüştürebilir. Örneğin, birçok Şema uygulamasında, for
gövdeye birden çok çağrıya genişleyen bir makrodur. Statik olarak yazılan dillerde, makrolar genellikle tür güvenlidir, yani iyi yazılmamış kod üretemezler.
C dil ailesinde, makrolar daha çok metinsel ikame gibidir. Bu da iyi yazılmamış veya sözdizimsel olarak yasal olmayan kod üretebilecekleri anlamına gelir.
Makro birleştiricilerde, "makrolar", "sanal talimatlar" a, yani CPU'nun doğal olarak desteklemediği, ancak faydalı olduğu talimatlara atıfta bulunur ve böylece montajcı, bu talimatları kullanmanıza izin verir ve bunları CPU'nun anladığı çoklu talimatlara genişletir .
Uygulama komut dosyasında "makro", kullanıcının "kaydedebileceği" ve "oynatabileceği" bir dizi eylemi ifade eder.
Bunların hepsi bir anlamda yürütülebilir kod türleridir, yani bir anlamda işlev olarak görülebilirler. Ancak, Lisp makroları söz konusu olduğunda, bunların giriş ve çıkışları program parçalarıdır. C durumunda, giriş ve çıkışları tokenlerdir. İlk üçü de derleme zamanında yürütüldükleri çok önemli bir ayrışmaya sahiptir . Aslında, C'nin önişlemci makroları, adından da anlaşılacağı gibi, kod derleyiciye ulaşmadan önce yürütülür .
C dili ailesinde bir makro tanımı , bir önişlemci komutu, tanımda derlenmeden makro çağrısında değiştirilen parametreli bir kod şablonu belirtir . Bu, tüm serbest değişkenlerin makro çağrısı bağlamında bağlanması gerektiği anlamına gelir. Yan etkisi olan parametre bağımsız değişkenleri i++
, parametrenin çoğul kullanımı ile tekrarlanabilir. 1 + 2
Bazı parametrelerin argümanının metinsel olarak değiştirilmesi x
derlemeden önce gerçekleşir ve beklenmeyen davranışlara x * 3
( 7
io 9
) neden olabilir . Makro tanımındaki makro gövdesinde bir hata, yalnızca makro çağrısında derleme yapıldığında gösterilir.
Fonksiyon tanımlama işlevi vücut bağlamına bağlı serbest değişkenler belirtir kodu; işlev çağrısı değil .
Bununla birlikte, makro görünüşte negatiftir, çağrıya, satır numarasına ve kaynak dosyaya, dize olarak bağımsız değişkene erişim sağlar .
Biraz daha soyut terimlerle ifade etmek gerekirse, makro bir işlev veriye olduğu gibi sözdizimidir. Bir işlev (özette) veriler üzerinde bazı dönüşümleri kapsar. Bağımsız değişkenlerini değerlendirilmiş veri olarak alır, üzerinde bazı işlemler yapar ve aynı zamanda sadece veri olan bir sonuç döndürür.
Buna karşılık bir makro değerlendirilmemiş bir sözdizimi alır ve bu konuda çalışır. C benzeri diller için sözdizimi simge düzeyinde gelir. LISP benzeri makroları olan diller için sözdizimini AST olarak gösterirler. Makro, yeni bir sözdizimi yığını döndürmelidir.
Bir makro genellikle derleme veya ön işleme sırasında "çağrı" makrosunun yerini hedef dilde tek tek talimatlarla değiştirerek yerine genişletilen bir şeyi ifade eder . Çalışma zamanında, genellikle makronun nerede başlayıp nerede bittiğine dair bir gösterge olmayacaktır.
Bu, bellekte ayrı olarak bulunan ve kontrolün çalışma zamanında geçirildiği yeniden kullanılabilir bir kod parçası olan bir alt rutinden farklıdır . Çoğu programlama dilinde "fonksiyonlar", "prosedürler" ve "yöntemler" bu kategoriye girer.
Olarak Jörg W MITTAG cevabı anlatılır tam detayları diller arasında değişir: bir de, örneğin, C, kaynak kodunda makro gerçekleştirdiği metin ikame gibidir; Lisp gibi bazılarında, Soyut Sözdizimi Ağacı gibi bir ara formun manipülasyonunu gerçekleştirir. Bazı gri alanlar da vardır: bazı diller "satır içi işlevler" için bir işlev gibi tanımlanmış, ancak bir makro gibi derlenmiş programa genişletilmiştir.
Çoğu dil, programcıları her bir alt program hakkında tek başına akıl yürütmeye, girişler ve çıkışlar için tür sözleşmeleri tanımlamaya ve arama kodu hakkında diğer bilgileri gizlemeye teşvik eder. Çoğu zaman, makroların oluşturmadığı bir alt programı çağırmak için bir performans etkisi vardır ve makrolar, programı bir alt programın yapamayacağı şekillerde değiştirebilir. Bu nedenle makrolar, daha az soyut temelde çalıştıkları için alt rutinlerden "daha düşük seviye" olarak kabul edilebilir.
Makro derleme sırasında yürütülür ve işlev çalışma zamanında yürütülür.
Misal:
#include <stdio.h>
#define macro_sum(x,y) (x+y)
int func_sum(x,y) {
return x+y;
}
int main(void) {
printf("%d\n", macro_sum(2,3));
printf("%d\n", func_sum(2,3));
return 0;
}
Derleme sırasında kod aslında şu şekilde değiştirilir:
#include <stdio.h>
int func_sum(x,y) {
return x+y;
}
int main(void) {
printf("%d\n", (2+3));
printf("%d\n", func_sum(2,3));
return 0;
}