#Defines girintileme


99

Bu #definetürlerin normalde hiçbir zaman girintili olmadığını biliyorum . Neden?

Şu anda #defines, #ifdefs, #elses, #endifs, vs.'nin korkunç bir karışımına sahip bir kod üzerinde çalışıyorum. Bunların tümü genellikle normal C koduyla karıştırılır. 'Lerin girintisiz #defineolması onları okumayı zorlaştırır. Ve girintili kod ile girintisiz kodun karışımı#define bir kabustur.

Leri girintilememenin faydası nedir #define? Onları girersem beni kötü biri yapar mı? Bu çok daha hoş değil mi?

#ifdef SDCC
    #if DEBUGGING == 1
        #if defined (pic18f2480)
            #define FLASH_MEMORY_END 0x3DC0
        #elif defined (pic18f2580)
            #define FLASH_MEMORY_END 0x7DC0
        #else
            #error "Can't set  up flash memory end!"
        #endif
    #else
        #if defined (pic18f2480)
            #define FLASH_MEMORY_END 0x4000
        #elif defined (pic18f2580)
            #define FLASH_MEMORY_END 0x8000
        #else
            #error "Can't set  up flash memory end!"
        #endif
    #endif
#else
    #if DEBUGGING == 1
        #define FLASH_MEMORY_END 0x7DC0
    #else
        #define FLASH_MEMORY_END 0x8000
    #endif
#endif

Yanıtlar:


103

Ön ANSI C ön işlemcisi, satırın başlangıcı ile "#" karakteri arasında boşluğa izin vermedi; baştaki "#" her zaman ilk sütuna yerleştirilmelidir.

Pre-ANSI C derleyicileri bugünlerde yok. Tercih ettiğiniz stili ("#" dan önceki boşluk veya "#" ile tanımlayıcı arasındaki boşluk) kullanın.

http://www.delorie.com/gnu/docs/gcc/cpp_48.html


26

Bazılarının daha önce söylediği gibi, bazı Pre-ANSI derleyicileri # satırındaki ilk karakter olmasını gerektirdi, ancak buna önişlemci direktifinin eklenmesini gerektirmedi, bu nedenle girinti bu şekilde yapıldı.

#ifdef SDCC
#  if DEBUGGING == 1
#    if defined (pic18f2480)
#      define FLASH_MEMORY_END 0x3DC0
#    elif defined (pic18f2580)
#      define FLASH_MEMORY_END 0x7DC0
#    else
#      error "Can't set  up flash memory end!"
#    endif
#  else
#    if defined (pic18f2480)
#      define FLASH_MEMORY_END 0x4000
#    elif defined (pic18f2580)
#      define FLASH_MEMORY_END 0x8000
#    else
#      error "Can't set  up flash memory end!"
#    endif
#  endif
#else
#  if DEBUGGING == 1
#    define FLASH_MEMORY_END 0x7DC0
#  else
#    define FLASH_MEMORY_END 0x8000
#  endif
#endif

Bu stili sık sık eski Unix başlıklarında görmüştüm, ancak sözdizimi renklendirmesi genellikle bu tür kodlarda başarısız olduğu için bundan nefret ediyorum. Ön işlemci yönergesi için göze çarpmaları için çok görünür bir renk kullanıyorum (bunlar meta düzeyindedir, dolayısıyla normal kod akışının bir parçası olmamalıdır). Hatta SO'nun diziyi kullanışlı bir şekilde renklendirmediğini bile görebilirsiniz.


16

Önişlemci direktiflerinin ayrıştırılmasıyla ilgili olarak, C99 standardı (ve ondan önceki C89 standardı), derleyici tarafından mantıksal olarak gerçekleştirilen işlemlerin sırası konusunda açıktı. Özellikle, bu kodun şu anlama geldiğine inanıyorum:

/* */ # /* */ include /* */ <stdio.h> /* */

eşdeğerdir:

#include <stdio.h>

Daha iyisi veya daha kötüsü için, '-std = c89 -pedantic' ile GCC 3.4.4, yorum yüklü satırı herhangi bir oranda kabul eder. Bunu bir stil olarak savunmuyorum - bir an için değil (korkunçtur). Ben sadece bunun mümkün olduğunu düşünüyorum.

ISO / IEC 9899: 1999 bölüm 5.1.1.2 Çeviri aşamaları diyor ki:

  1. [Trigraflar dahil karakter eşleme]

  2. [Satır ekleme - ters eğik çizgi yeni satırı kaldırma]

  3. Kaynak dosya, ön işlem belirteçlerine ve beyaz boşluk karakter dizilerine (yorumlar dahil) ayrıştırılır. Bir kaynak dosya, kısmi bir ön işleme belirteciyle veya kısmi bir yorumla sona ermemelidir. Her yorum bir boşluk karakteri ile değiştirilir. Yeni satır karakterleri korunur. Yeni satır dışındaki her boş olmayan boşluk karakteri dizisinin korunup korunmayacağı veya bir boşluk karakteriyle değiştirilip değiştirilmeyeceği uygulama tanımlıdır.

  4. Ön işleme yönergeleri yürütülür, makro çağrıları genişletilir, [...]

Bölüm 6.10 Ön işleme yönergeleri şunları söylüyor:

Bir ön işleme yönergesi, kaynak dosyadaki ilk karakter olan (isteğe bağlı olarak yeni satır karakterleri içermeyen beyaz boşluktan sonra) # önişleme belirteci ile başlayan bir ön işleme dizgecinden oluşur (çeviri aşaması 4'ün başlangıcında) veya en az bir yeni satır karakteri içeren beyaz boşluğu takip eder ve bir sonraki yeni satır karakteri ile biter.

Olası tek anlaşmazlık, parantez içindeki '(çeviri aşaması 4'ün başlangıcında)' ifadesidir; bu, hash'den önceki yorumların, aksi takdirde aşama 4'ün sonuna kadar boşluklarla değiştirilmeyecekleri için mevcut olmaması gerektiği anlamına gelebilir.

Başkalarının da belirttiği gibi, ön-standart C önişlemcileri çeşitli şekillerde aynı şekilde davranmıyorlardı ve önişlemci direktiflerinden önceki ve önişlemci direktiflerindeki boşluklar, farklı derleyicilerin farklı şeyler yaptığı alanlardan biriydi. .

Ters eğik çizgi-satırsonu kaldırma işleminin yorumlar analiz edilmeden önce yapılması dikkat çekicidir. Sonuç olarak, //yorumları ters eğik çizgiyle bitirmemelisiniz.


7

Neden daha yaygın olmadığını bilmiyorum. Önişlemci direktiflerini girintilemeyi sevdiğim zamanlar kesinlikle vardır.

Sürekli yoluma çıkan (ve bazen beni denemekten vazgeçmeye ikna eden) bir şey, birçok veya çoğu editörün / IDE'nin en ufak bir provokasyonda yönergeyi 1. sütuna atmasıdır. Bu cehennem kadar can sıkıcı.


5

Bugünlerde bunun esas olarak bir stil seçimi olduğuna inanıyorum. Ben düşünüyorum uzak geçmişte bir noktada, tüm derleyiciler önişlemci tanımlarınızı girinti kavramını destekledi. Biraz araştırma yaptım ve bu iddiayı yedekleyemedim. Ancak her durumda, tüm modern derleyicilerin ön işlemci makrosu girintileme fikrini desteklediği görülmektedir. Yine de C veya C ++ standardının bir kopyasına sahip değilim, bu yüzden bunun standart davranış olup olmadığını bilmiyorum.

İyi bir tarz olup olmadığına gelince. Şahsen, hepsini solda tutma fikrini seviyorum. Size onları aramak için tutarlı bir yer sağlar. Evet, çok iç içe geçmiş makrolar olduğunda can sıkıcı olabilir. Ancak, onları girintilerseniz, sonunda daha da tuhaf görünen bir kod elde edersiniz.

#if COND1
void foo() {
  #if COND2
  int i;
    #if COND3
  i = someFunction()
  cout << i << eol;
    #endif
  #endif
}
#endif

14
Bu kodun tuhaf görünmesinin nedeni, iki girinti "akışı" oluşturmuş olmanızdır. 4. satırı bir seviye daha girintili yapardım ve 6 ve 7 numaralı satırları iki seviye daha girintili yapardım.
Kevin Laity

3
Tamamen katılıyorum. Bazen diş telleri bile koyuyorum, böylece # if'ler tıpkı eğer'ler gibi görünüyor.
baash05

3
Kodumu , gerçek kodumun olduğu kısımlarda hiç #ifdef satır olmaması için çok sıkı bir şekilde düzenlemeye çalışıyorum . Bunun yerine, koşullu maddelere ihtiyacım olursa, ya onu faktörlü fonksiyonlara koyarım ya da makroları çarpanlarından çıkarırım; bu şekilde bulduğum çok daha net (en azından benim için öyle). İdeal olarak, tüm bu çarpanlara ayrılan kısımlar diğer dosyalarda olacaktır (başlıklar veya koşullu olarak derlenmiş kaynak dosyalar; kodun hangi platform için oluşturulduğu olağan "koşul").
Donal Dostları

2
4. satırları bir seviye ve 6. ve 7. satırları iki seviye girintilerim.
Rocketmagnet

3

Verdiğiniz örnek için, bu kadar karmaşık bir iç içe yerleştirilmiş yönergeler yapısına sahip olduğunuz için, onu daha net hale getirmek için girinti kullanmak uygun olabilir.

Kişisel olarak, çoğu zaman girintili olmamalarını sağlamanın yararlı olduğunu düşünüyorum, çünkü bu direktifler kodunuzun geri kalanından ayrı işliyor. #İfdef gibi yönergeler, derleyici kodunuzu görmeden ön işlemci tarafından işlenir, bu nedenle bir #ifdef yönergesinden sonraki bir kod bloğu derlenemeyebilir bile .

Direktifleri kodunuzun geri kalanından görsel olarak ayrı tutmak, kodun arasına serpiştirildiklerinde (verdiğiniz örnekte olduğu gibi özel bir direktif bloğu yerine) daha önemlidir.


3
IP'nin bakış açısından, derlenmemiş bir şey ile bir jmp nedeniyle ulaşılamayan bir şey arasındaki fark nedir?
baash05

2

Şu anda #defines, #ifdefs, #elses, #endifs, #etc gibi korkunç bir karışımı olan bir kod üzerinde çalışıyorum. Tüm bunlar genellikle normal C koduyla karıştırılır. # Tanımların girintili olmaması, okumayı zorlaştırır. Ve girintili kod ile girintisiz # tanımlarının karışımı bir kabustur.

Yaygın bir çözüm, direktifleri yorumlamaktır, böylece neye işaret ettiklerini kolayca bilirsiniz:

#ifdef FOO
/* a lot of code */
#endif /* FOO */

#ifndef FOO
/* a lot of code */
#endif /* not FOO */

6
Bu stili gördüm, patronum kullanıyor. Ve kodunun geri kalanı gibi, bu da bir karmaşa yaratıyor. Normal if () ifadelerinizden tüm girintiyi kaldırdığınızı ve bunun yerine bu yorumları kullandığınızı hayal edin. Neye atıfta bulunduklarını kolayca göremediğinizden şikayet edeceksiniz.
Rocketmagnet

2

Neredeyse mevcut tüm C / CPP derleyicilerinde kısıtlı değildir. Kodu nasıl hizalamak istediğinize karar vermek kullanıcıya bağlıdır. Çok mutlu kodlama.


1
İyi cevap. Belirli bir stil kılavuzu referansı ekleyerek bunu geliştirebilir misiniz?
EtherDragon
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.