Karşılaştığınız en kötü gerçek dünya makroları / işlemci öncesi kötüye kullanım nedir?


176

Karşılaştığınız en kötü gerçek dünya makroları / işlemci öncesi kötüye kullanım nedir (lütfen hiçbir IOCCC cevabı * haha ​​* yok)?

Gerçekten eğlenceli ise lütfen kısa bir snippet veya hikaye ekleyin. Amaç, insanlara her zaman “asla makro kullanma” demelerini değil, bir şeyler öğretmektir.


ps: Daha önce makroları kullandım ... ama genellikle sonunda "gerçek" bir çözümüm olduğunda onlardan kurtulurum (gerçek çözüm bir makroya benzeyecek şekilde sıralı olsa bile).


Bonus: Makronun makro olmayan bir çözümden gerçekten daha iyi olduğu bir örnek verin.

İlgili soru: C ++ makroları ne zaman faydalıdır?


Makroların elinde yaşadığım yaygın kötüye kullanıma dikkat çektiği için +1.
i_am_jorf

37
#define true false // mutlu hata ayıklama :)
n0rd

Topluluk wiki, hiç kimsenin bu soru veya cevapları üzerinde yukarı / aşağı oyla itibar kazanamayacağı veya kaybetmeyeceği anlamına gelir. Birçok kişi bu gibi soruları itibar kazanmanın ucuz ve kolay yolları olarak görür, bu yüzden bunu topluluk wiki'si olarak işaretlerseniz, insanların tümünün bükülme ve kapanma olasılığı daha düşüktür.
Graeme Perrow

2
"insanlar her şeyden şekil alır ve onu kapatır": Yığın taşması üzerinde komik / komik içerik istemediğinizi mi ima ediyorsunuz?
Trevor Boyd Smith

2
Hızlı bir nokta, ön işlemci dilin bir parçasıdır ve bu nedenle her şey gibi, kötü / yanlış değildir.
Bay Boy

Yanıtlar:


410

Bellekten şöyle bir şey görünüyordu:

#define RETURN(result) return (result);}

int myfunction1(args) {
    int x = 0;
    // do something
    RETURN(x)

int myfunction2(args) {
    int y = 0;
    // do something
    RETURN(y)

int myfunction3(args) {
    int z = 0;
    // do something
    RETURN(z)

Evet bu doğru, hiçbir fonksiyonda kapanış parantezi yok. Sözdizimi vurgulama bir karışıklıktı, bu yüzden düzenlemek için vi kullandı (vim değil, sözdizimi renklendirmesi var!)

Daha çok montaj dilinde çalışan bir Rus programcıydı. Daha önce çok sınırlı belleğe sahip sistemlerde çalıştığı için mümkün olduğunca çok bayt kaydetme konusunda fanatikti. "Uydu içindi. Sadece çok az bayt, bu yüzden her baytı birçok şey için kullanıyoruz." (bitlerle uğraşmak, makine talimatı baytlarını sayısal değerleri için tekrar kullanmak) Ne tür uydular bulmaya çalıştığımda, sadece "Uydu etrafında yörüngede. Yörüngede yapmak için."

Başka iki tuhaflığı daha vardı: Monitörünün üstüne "Kimin izlediğini bilmek için" monte edilmiş bir dışbükey ayna ve ara sıra hızlı bir on itme yapmak için sandalyesinden ani bir çıkış. Bu sonuncuyu "Derleyici kodda hata buldu. Bu bir ceza" olarak açıkladı.


87
Msgstr "Derleyici kodda hata buldu. Bu ceza". !! Şirket sizi buldu ... diğer çalışanlara ceza!
Öğrenme

227
Sovyet Rusya'da, program SİZİ derler!
Crashworks

53
Derleyici hatası "ceza" hakkında okuduğumda, ilk düşündüğüm şey "Dobby ellerini ütülemek zorunda kaldı".
Graeme Perrow

124
Bence bir derleyici kodumuzda bir hata bulduğunda hepimiz 10 şınav yaptıkça programcılar (kendim dahil) çok daha uygun olacağını düşünüyorum. Bu, derleme yoluyla test oluşumunu da azaltabilir.
MikeyB

5
Bu adam harika görünüyor. Ama evet, bunun kod boyutunu nasıl geliştirmesi gerektiğini anlamıyorum.
jalf

274

En kötüsü:

#define InterlockedIncrement(x) (x)++
#define InterlockedDecrement(x) (x)--

Hayatımın iki gününü çok iş parçacıklı COM ref sayma sorununu izleyerek geçirdim çünkü bazı salak bunu bir başlık dosyasına koydu. O zaman çalıştığım şirketten bahsetmeyeceğim.

Bu hikayenin ahlaki mi? Bir şey anlamıyorsanız, belgeleri okuyun ve hakkında bilgi edinin. Sadece gitmesine izin verme.


146
@Joshua: Bu kodu çok iş parçacıklı bir ortamda çalıştırırsanız, istemeden yapabilirsiniz
1800 BİLGİ

11
"Eğer bir şey anlamıyorsanız, belgeleri okuyun ve bu konuda bilgi edinin. Sadece ortadan kaldırmayın." - AMEN!
Paul Alexander

2
@ 1800 Bilgi: Bence sadece oy kaybedersiniz, bu yüzden size bir tane veremem; p
wkf

5
C ++ olmayan bir programcı olarak beni affet: Burada ana sorun bir threadsafe işlevi non-threadsafe bir dönüştürülür mü? Ya da o InterlockedIncrement bir işaretçi bekler, bu yüzden şimdi işaret etmek yerine işaretçiyi artıracak mısınız? Ya da her ikisi de?
Tim Pietzcker

38
Sorun, InterlockedIncrement normalde Windows API'de tanımlanan bir atomik fonksiyon olmasıdır. İnsanlar InterlockedIncrement'ı çağırdığında, atomik olarak yürütülmesi garanti edilen bir işleve çağrı yapmayı beklerler. Bunun yerine, birisi aynı ada sahip, atomik olmayan düz bir artışı değerlendiren bir makro tanımladı
jalf

166
#define ever (;;)
for ever { 
   ...
}

52
(;;) için <#define sonsuza kadar tercih ederim, böylece <sonsuza kadar {...}> yazabilirsiniz
paxdiablo

birisi HİÇ şey için kayıp izleri ile okula gittim ... o kitapta olduğu gibi boğuldu :-)
TofuBeer

6
Pax'ın önerisi doğrudan K&R'den değil mi? Yine de, çabaya değmez, söyleyebilirim.
Jon Ericson

Aslında hiç de fena değil. for (;;)Deyim kullanmıyorum , aksi takdirde hemen bu makroyu koduma eklerdim.
09:00 AnT

1
@hayalci: Emacs lisp (ve bazı yaygın lisp uygulamalarında) şunları yapabilir (defmacro ever ())ve sonra(require 'cl (ever))
Joe D

145
#include <iostream>
#define System S s;s
#define public
#define static
#define void int
#define main(x) main()
struct F{void println(char* s){std::cout << s << std::endl;}};
struct S{F out;};

public static void main(String[] args) {
  System.out.println("Hello World!");
}

Zorluk: Herkes daha az tanım ve yapı ile yapabilir mi? ;-)


19
bir java-c-dönüştürücü yazdınız! horray!
Andreas Petersson

25
"Saldırgan" olarak bildirildi. (Ben çocuk!)
Annika Backstrom

40
Bu çok güzel ya da çok iğrenç.
Chris Lutz

38
@ Mark - Bu beyan publicve static as nothing, olarak void` intve main(x)sıra main(), bu yüzden public static void main(String[] args)içine dönüşler int main(). Sonra Systemdönüşür S s;s, bu nedenle System.out.println("Hello World!");döner içine S s; s.out.println("Hello World!");hangi çağırır printlnişlevi Fiçinde yapı Syapı.
Chris Lutz

2
Şuna bir göz atın: mailcom.com/ioccc/chia/chia.c (indirin ve derleyin)
Roberto Bonvallet

130
#define private public

Bunu daha önce yaptım. Bazen bir üye değişkeni değiştirmeniz veya bazı üçüncü taraf kodlarında değiştiremeyeceğiniz bir işlevi geçersiz kılmanız gerekir ve bunlar sizin için bir erişimci sağlamadı.
Michael Kristofik

30
ünite testi için vay, nesne tasarımının hayaletleri gece sizi rahatsız edecek olsa bile, bu yararlı olabilir.
Epaga

12
Hmmm, tanımsız davranış, tek tanım kuralının kolay ihlali, potansiyel yerleşim farklılıkları. Evet, bu bir kazanan.
David Thornley

10
Böylece, özel ve genel öğelere erişebilirim, ancak korunan öğelere erişemiyorum ve classanahtar kelime ile ilk erişim değiştirici arasındaki öğelere erişemiyorum.
Ken Bloom

3
@Ken:#define class struct #define protected public
Yakov Galka

107
#define if while

Birine şaka yapıldı, etkilenenler tarafından eğlenceli bulunmadı


22
#define ise daha da sinsi olur.
starblue

7
İfadenizi açıklığa kavuşturmalıyız. Etkilenen insanlar tarafından eğlenceli bulunmadı . :-)
Andrew Shepherd

6
Ödevler yaptığımda, öğretmenlerimi rahatsız etmek için sık sık bu tür şeyleri bilerek yaptım.
pyon

15
Bu iyi bir şaka ama "başka" ifadeler varsa derlenmeyecek. (True) en etkili ise (x) ise #define olduğunu buldum.
Grafik Noob

32
Her zaman #define sizeof (x) rand ()
Jon

106

İğrenç:

#define begin {
#define end }
/* and so on */

Cidden, Pascal'da kod yazmak istiyorsanız, bir Pascal derleyicisi satın alın, güzel C dilini yok etmeyin.


45
Şimdi yeterince akıllı bir başlık dosyasıyla hangi dilleri simüle edebileceğimi merak ediyorsun.
Kertenkele Bill

47
C güzel değil. Oldukça çirkin.
rlbond

27
Güzelliği sadeliğinde yatar. Meclis dilinin tüm hızına sahip olduğu söylenmiştir ... montaj dili :-) Şişirilmiş C ++ 'ı tercih ederim (büyük kütüphanesi nedeniyle gün işimde Java'yı tercih etsem de).
paxdiablo

9
Gerçekten değil. Bourne kabuğunun orijinal kaynağını bulun. Tam olarak bunu bir tür piç ALGOL benzeri karışıklık elde etmek için yaptı.
RBerteig

3
#define DO (int _i = 0; _i <= 1; ++ _ i) {if (_i == 1) //// LINE BREAK //// #define IF (koşul); (! (koşul)) kırılırsa; } //// LINE BREAK //// DO printf ("a") EĞER (1 == 2);
Adrian Panasiuk

93

'Mimar', çok mütevazı bir adam, tipini biliyorsunuz, aşağıdakilere sahipti:

#define retrun return

çünkü hızlı yazmayı severdi. Beyin cerrahı, ondan daha akıllı (hemen hemen herkes) olan insanlara bağırmayı severdi ve siyah kuşaklarını üzerlerinde kullanmakla tehdit ediyordu.


Ben bu yazım hatalarını o kadar çok yaptım.
Joshua

4
daha ziyade editörünüze otomatik olarak geri dönmeyi öğretin. En azından IRC müvekkilim için böyle bir hackleme yaptım
Tetha

1
Hey, sanırım o 'mimar'la da çalışıyordum. Sonunda egosunu yatıştırması gerektiğinde yeniden kıdemli mimar aldı.
BIBD

1
Yazamadığım ve 'rn' haber okuyucusunun başlatılması ve sunucuya bağlanması 5 dakika sürdüğü için bash içinde 'rn' yeniden tanımlanmıştım.
Martin Beckett

2
Sadece yeni bir terminal açamazsınız (veya başka bir vt'ye geçemezsiniz) killall rn?
Joe D

69

Gerçek dünya? MSVC, minmax.h içinde çağrılmış maxve minstandart std::numeric_limits<T>::max()işlevi her kullanacağımda bir derleyici hatasına neden olan makrolara sahiptir .


2
Ah, evet, bu yüzden MS'ye özel olanlardan sonra akıl sağlığına kavuşan # undef'lerle özel bir
başlığım vardı

3
(Std :: numeric_limits <T> :: max) () ile çözüldü Ama evet, oldukça can sıkıcı.
rlbond

36
C / C ++ -> Önişlemci -> Önişlemci Tanımları altındaki proje özelliklerinize NOMINMAX'ı ekleyin.
mattnewport

18
Bu makrolar, MS üstbilgilerinde min'den daha uzun süre vardı ve max, C ++ Standart Kitaplığı'nda bulunuyordu.
Richard

4
Diğer dış bağımlılıklarınızın dördü de, kötü parantezli makrolardan iyi yazılmış şablonlara kadar değişen, çeşitli derecelerde emiciliğin kendi min / maks'lerini tanımladığında ve bunlardan birinin tanımlanmayı imkansız hale getirmesi gerektiğinde daha da kötüdür. ya da başka türlü atlayın ... Kitabımda dil% 50 suçlanıyor.
Roman Starkov

58

Pascal sözdizimi ile Fransızca anahtar kelimeler arasında bir karışım:

#define debut {
#define fin }
#define si if(
#define alors ){
#define sinon }else{
#define finsi }

36
#define zut_alors çıkış (-1)
MikeyB

4
Bu harika ve beni yüksek sesle güldürdü. Yani, bu temelde C temelde uygulanan Basic yerelleştirilmiş bir Fransızca sürümü?
Bobby

56

Raymond Chen, akış kontrol makrolarını kullanmaya karşı gerçekten iyi bir sıralamaya sahip . Onun en iyi örneği doğrudan orijinal Bourne kabuğu kaynak kodundan:

ADDRESS alloc(nbytes)
    POS     nbytes;
{
    REG POS rbytes = round(nbytes+BYTESPERWORD,BYTESPERWORD);

    LOOP    INT     c=0;
    REG BLKPTR  p = blokp;
    REG BLKPTR  q;
    REP IF !busy(p)
        THEN    WHILE !busy(q = p->word) DO p->word = q->word OD
        IF ADR(q)-ADR(p) >= rbytes
        THEN    blokp = BLK(ADR(p)+rbytes);
            IF q > blokp
            THEN    blokp->word = p->word;
            FI
            p->word=BLK(Rcheat(blokp)|BUSY);
            return(ADR(p+1));
        FI
        FI
        q = p; p = BLK(Rcheat(p->word)&~BUSY);
    PER p>q ORF (c++)==0 DONE
    addblok(rbytes);
    POOL
}

2
İki nokta: bir, bu macun orijinal girintiyi berbat etti. Ve iki, kod ne olduğu için iyi görünüyor: 1970'lerde ateşli bir Algol-68 hayranı tarafından Unix C. Şanslı sertlik neden kendini tuhaf bir tarzda ifade edebiliyorsa, neden Steve Bourne? Elbette, Algol 68'i bilmeyen onu korumaya mahkum olan biri, kendi zevklerini genişletme şansını takdir etmeyebilir.
Darius Bacon

Bu önerilen bir programlama tarzı yerine Steve Bourne tarafından bir şaka olarak düşünülebilir düşünüyorum
Martin Beckett

2
Gördüm ki if... else... elif... five case... daha esacönce (Bourne'nin sh için icat ettiği dilde), ama loop... poolgerçek bir mücevher.
ocaklar

54

Yarışma için chaos-pp adlı bir mücevher göndermek istiyorum , önişlemci makroları aracılığıyla işlevsel bir dil uygulayan .

Örneklerden biri, tamamen önişlemci tarafından 500. fibonacci sayısının hesaplanmasıdır:

Önişlemciden önceki orijinal kod şöyle görünür:

int main(void) {
   printf
     ("The 500th Fibonacci number is "
      ORDER_PP(8stringize(8to_lit(8fib(8nat(5,0,0)))))
      ".\n");
   return 0;
}

dosyayı önceden işlerken aşağıdaki sonucu alırız (oldukça uzun bir bekleyişten sonra):

$ cpp -I../inc fibonacci.c 2>/dev/null | tail
  return fib_iter(n, 0, 1);
}
# 63 "fibonacci.c"
int main(void) {
   printf
     ("The 500th Fibonacci number is "
      "139423224561697880139724382870407283950070256587697307264108962948325571622863290691557658876222521294125"
      ".\n");
   return 0;
}

1
Kodu CVS'den alabilir ve bir göz atabilirsiniz. Bir süre önce tökezlediğimde bu konuda daha fazla ayrıntı koydum: bnpcs.blogspot.com/2009/02/… Ortaya çıkan kodda hata ayıklama problemi için değilse (çok uzun satırlara sahip olma sorunu) böyle bir "dil" tarafından üretilir), C için pratik bir kod üreticisi olarak bile kullanılabilirdi
Andrew Y

Sonsuza kadar derlemeyi
sürdüğünü

52

Doğrudan Qt:

#define slots   /* */
#define signals /* */

Boost :: sinyalleri olarak diğer libs ile etkileşim kurmak gerçekten güzel ... Sadece bir örnek olarak, Qt'ta komik görünümlü kodlar yaratan birçok kişi var:

class X : public QObject {
   Q_OBJECT
private slots:
   //...
public signals:
   //...
};

Ve bu C ++ ... ama aniden:

boost::signals::trackable

Artık geçerli C ++ değil.


5
:) Yani diğer kütüphaneleri boşuna bozan bir makro. Beklediğimden daha da iyi :)
David Rodríguez - dribeas

38
Qt çok bölgesel ve ad alanını işgal etmeye çalışan diğer kütüphanelere şiddetle saldıracak :)
Jeremy Friesner

21
Ne yazık ki Qt, makroların kullanımı ile ad alanının dışındaki kütüphanelere saldırıyor
David Rodríguez - dribeas

7
Neyse ki artırmak ::
signal2

9
Bu etkileşimden korkuyorsanız Q_SIGNALS ve Q_SLOTS kullanın.
Tadeusz A. Kadłubowski

50

Windows.h, makroları kötüye kullanan birçok işleve sahiptir.


MrValdez, Windows.h dosyasında bulunan GetObject makrosu tarafından rahatsız edildi

GetObject makrosu, GetObject () işlevini GetObjectA () veya GetObjectW () olarak değiştirir (derlemenin sırasıyla unicode olmayan ve unicode'da derlenmesine bağlı olarak)

MrValdez GetObject fonksiyon satırından önce yapmaktan nefret eder

#undef GetObject

Object *GetObject()

Alternatif olarak işlev adını GetGameObject () gibi başka bir adla değiştirmek


yorumlarda jdkoftinoff çivilenmiş: Sorun tüm windows API fonksiyonları makro olmasıdır.

Adam Rosenfield, windows.h sorunlarını eklemeden önce NOGDI, WIN32_LEAN_AND_MEAN, NOMINMAX, vb. Tanımlayarak sorunların giderilebileceğini belirtti.


3
Tabii ki çeşitli GDI işlevlerini kullanmanız gerekmemesi şartıyla windows.h'yi eklemeden önce # define'ing NOGDI'yi bastırabilirsiniz. WIN32_LEAN_AND_MEAN, NOMINMAX vb. Gibi başka şeylerin tanımlanmasını veya dahil edilmesini engelleyen başka makrolar da vardır.
Adam Rosenfield

1
GetObject oldukça genel bir işlev adıdır. Belki de çarpışmadan kaçınmak için bağlam verildiğinde daha açıklayıcı bir isim kullanabilirsiniz. Ancak, bu oldukça kötü bir makro durumdur.
Mart'ta strager

1
Win32'nin API adlarını FooA ve FooW'a dönüştürmek için tüm makrolara sahip olması oldukça can sıkıcı bir durum. SendMessage ile ilgili sorunumuz var.
i_am_jorf

6
Sorun, tüm Windows API işlevlerinin makro olmasıdır. Beni biraz ısırdı GetTickCount (). Programlamamın çoğunu pencerelerin dışında yaptığım için, Windows üstbilgilerindeki tüm tanımları buldum ve daha sonra uyumluluğu önceden doğrulamak için hepsini tanımlayan kendi içerme dosyamı yaptım.
jdkoftinoff

12
Bir kazananımız olduğunu düşünüyorum. Gerçek dünya, gülünç derecede kötü bir fikir ve çok sayıda masum programcıyı etkiledi. Microsoft'ta bu taştan kim sorumlu ise bir savaş suçlusu olarak düşünülmelidir ... En iyi tarafı, Microsoft'un GetObject, SendMessage veya CreateWindow gibi inanılmaz derecede yaygın isimleri kullanma hakkında iki kez düşünmemesi.
jalf

45
#define return if (std::random(1000) < 2) throw std::exception(); else return

bu çok kötü. Rastgele, yani her zaman farklı yerlerde ateş ediyor, genellikle kendi başına başarısız olabilecek bazı kodları olan dönüş ifadesini değiştiriyor, hiç şüphelenmeyeceğiniz masum görünümlü bir anahtar kelimeyi değiştiriyor ve kullanıyor std uzayından istisna olduğundan, kaynağını bulmak için kaynaklarınızda arama yapmaya çalışmazsınız. Sadece harika.


4
Sadece bunu test ettim, en azından rastgele bir eksik içerme nedeniyle varsayılan olarak derlenmiyor ve o zaman kırmızı renkte çalkalanıyor. Ancak, kazara içerme varsa, işler daha da kötüleşir - VC ++ 2010 hala bir anahtar kelime olarak işaretler ve makro genişletme araç ipucunu göstermez, bu nedenle IDE'den bunu bulmak için yardım yok: - /
OregonGhost

Onu seviyorum! Saf deha. Kimse başaramadı Bu uygulama "Hata Ayıklama" ne kadar iyi bakabilirsiniz düşünün.
brice

36

Bir iş arkadaşı ve ben bu iki mücevher nesne akışı kodumuzun bazılarında bulundu. Bu makrolar, akış gerçekleştiren HER TEK sınıf dosyasında başlatıldı . Bu iğrenç kod sadece kod tabanımıza yayılmakla kalmadı, orijinal yazara yaklaştığımızda, dahili wiki'mizde bunu burada yapmaya çalıştığı şeyi başarmanın tek yolu olarak savunan 7 sayfalık bir makale yazdı.

Söylemeye gerek yok, o zamandan beri yeniden düzenlendi ve kod tabanımızda artık kullanılmıyor.

Vurgulanan anahtar kelimeler tarafından atılmayın. Bu TÜM bir makro

#define DECLARE_MODIFICATION_REQUEST_PACKET( T )                                                \
namespace NameSpace                                                                     \
{                                                                                       \
                                                                                        \
class T##ElementModificationRequestPacket;                                                          \
}                                                                                       \
                                                                                        \
DECLARE_STREAMING_TEMPLATES( IMPEXP_COMMON_TEMPLATE_DECLARE, NameSpace::ElementModificationRequestPacket<T>, OtherNameSpace::NetPacketBase )    \
DLLIMPEXP_COMMON_TEMPLATE_DECLARE( NameSpace::ElementModificationRequestPacket<T> )     \
DECLARE_AUTOGENERATION_TEMPLATES( DLLIMPEXP_COMMON_TEMPLATE_DECLARE, NameSpace::T##ModificationRequestPacket, NameSpace::ElementModificationRequestPacket<T> )      \
                                                                                        \
namespace NameSpace {                                                                   \
class DLLIMPEXP_COMMON T##ModificationRequestPacket : public ElementModificationRequestPacket<T>\
{                                                                                       \
public:                                                                                 \
    T##ModificationRequestPacket( NetBase * pParent )                                   \
    : ElementModificationRequestPacket<T>( pParent ), m_Gen() {}                            \
                                                                                        \
    T##ModificationRequestPacket( NetBase * pParent,                                    \
                            Action          eAction,                                    \
                            const T &   rT )                                            \
    : ElementModificationRequestPacket<T>( pParent, eAction, rT ), m_Gen() {}               \
                                                                                        \
    T##ModificationRequestPacket( const T##ModificationRequestPacket & rhs )                        \
    : ElementModificationRequestPacket<T>( rhs ), m_Gen() {}                                \
                                                                                        \
    virtual                     ~T##ModificationRequestPacket( void ) {}                        \
                                                                                        \
    virtual Uint32          GetPacketTypeID( void ) const                           \
    {                                                                                   \
        return Net::T##_Modification_REQUEST_PACKET;                                        \
    }                                                                                   \
                                                                                        \
    virtual OtherNameSpace::ClassID GetClassID ( void ) const                           \
    {                                                                                   \
        return OtherNameSpace::NetBase::GenerateHeader( OtherNameSpace::ID__LICENSING,  \
                                                         Net::T##_Modification_REQUEST_PACKET );    \
    }                                                                                   \
                                                                                        \
    virtual T##ModificationRequestPacket * Create( void ) const                             \
    { return new T##ModificationRequestPacket( m_pParent ); }                                   \
                                                                                        \
    T##ModificationRequestPacket() {}                                                           \
                                                                                        \
protected:                                                                              \
    OtherNameSpace::ObjectAutogeneration<T##ModificationRequestPacket> m_Gen;                       \
                                                                                        \
    friend class OtherNameSpace::StreamingBase::StreamingClassInfoT<T##ModificationRequestPacket >;                     \
    OtherNameSpace::StreamingBase::Streaming<T##ModificationRequestPacket, ElementModificationRequestPacket<T> >    m_Stream;   \
                                                                                        \
};                                                                                      \
}                                                                                       \
DLLIMPEXP_COMMON_TEMPLATE_DECLARE( ThirdNameSpace::ListenerBase<const NameSpace::T##ModificationRequestPacket> )            \
DLLIMPEXP_COMMON_TEMPLATE_DECLARE( ThirdNameSpace::BroadcasterT<const NameSpace::T##ModificationRequestPacket> )            \
typedef  ThirdNameSpace::BroadcasterT<const T##ModificationRequestPacket>  T##ModifiedBroadcaster;



#define IMPLEMENT_MODIFICATION_REQUEST_PACKET( T )                                                                  \
DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE( NameSpace::ElementModificationRequestPacket<T> )                         \
DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE( ThirdNameSpace::ListenerBase<const NameSpace::T##ModificationRequestPacket> )        \
DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE( ThirdNameSpace::BroadcasterT<const NameSpace::T##ModificationRequestPacket> )        \
INSTANTIATE_STREAMING_TEMPLATES( DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE, NameSpace::ElementModificationRequestPacket<T>, OtherNameSpace::NetPacketBase ) \
INSTANTIATE_AUTOGENERATION_TEMPLATES( DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE, NameSpace::T##ModificationRequestPacket, NameSpace::ElementModificationRequestPacket<T> )

Güncelleme (17 Aralık 2009):

Bu iğrenç makro yazarla ilgili daha iyi haberler. Ağustos itibariyle, bu canavarlıktan sorumlu çalışan görevden alındı.


3
açıkçası hiç duymamıştı: "Hata ayıklama, ilk etapta kodu yazmaktan iki kat daha zor. Bu nedenle, kodu olabildiğince akıllıca yazarsanız, tanım olarak, hata ayıklamak için yeterince akıllı değilsiniz." -Brian W. Kernighan
Trevor Boyd Smith

33

Aşağıdakileri kendim yaptım ve sanırım ondan bir şeyler öğrendim.

1992'de küçük bir Lisp tercümanı yazdım. Normal C'de değil, yorumlanmış C benzeri bir dilde uygulandı. Bu C benzeri dil, standart C ön işlemcisini kullandı.

Lisp yorumlayıcısı elbette fonksiyonları içeriyordu bir listedeki ilk öğeyi döndürmek için Lisp'de kullanılan araba ve listenin geri kalanını döndüren cdr . Onlar böyle uygulandı:

LISPID car(LISPID id) {
    CHECK_CONS("car", 1, id);
    return cons_cars[id - CONS_OFFSET];
} /* car */

LISPID cdr(LISPID id) {
    CHECK_CONS("cdr", 1, id);
    return cons_cdrs[id - CONS_OFFSET];
} /* cdr */

(Hiçbir yapı olmadığı için veriler dizilerde saklandı. CONS_OFFSET sabit 1000'dir.)

araba ve cdr Lisp'de sık kullanılır ve kısadır ve işlev çağrıları uygulama dilinde çok hızlı olmadığından, kodumu bu iki Lisp işlevini makro olarak uygulayarak optimize ettim:

#define car(id) (CHECK_CONS("car", 1, (id)), cons_cars[(id) - CONS_OFFSET])
#define cdr(id) (CHECK_CONS("car", 1, (id)), cons_cdrs[(id) - CONS_OFFSET])

CHECK_CONS , argümanının aslında bir liste olduğunu kontrol eder ve bu da yorumlayıcıda sıklıkla kullanıldığından ve kısa olduğundan, bunu bir makro olarak da yazdım:

#define CHECK_CONS(fun, pos, arg)   \
    (!IS_CONS(arg) ?        \
        LISP_ERROR("Arg " + pos + " to " + fun +    \
                   " must be a list: " + lispid2string(arg)) : 0)

IS_CONS ve LISP_ERROR da sık sık kullanıldılar, bu yüzden onları da makrolara dönüştürdüm:

#define IS_CONS(id) \
    (   intp(id) && (id) >= CONS_OFFSET     \
     && ((id) - CONS_OFFSET) < sizeof(cons_cars))

#define LISP_ERROR(str)     (throw((str) + "\n"))

Mantıklı görünüyor?

Ama sonra, tüm sistem neden bu hatta çöktü:

id2 = car(car(car(car((id1))));

Sorunu bulmak için uzun bir süre çalıştım, nihayet bu kısa hattın ön işlemci tarafından neye genişletildiğini kontrol edene kadar. Burada netlik için satırlara (502 tanesi) bölündüğüm 31370 karakterlik bir satıra genişletildi:

id2 = ((!(intp( (((!(intp( (((!(intp( (((!(intp( (id1)) && (
(id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))
&& ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && (
(id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000]))) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (((!(intp( (id1)) && ( (id1))
>= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg "
+ 1 + " to " + "car" + " must be a list: " + lispid2string(
(id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))) + "\n")) : 0),
cons_cars[(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) && ( (((!(intp( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) >= 1000 && (( (((!(intp(
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) - 1000) < sizeof(cons_cars))
? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 &&
(( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to
" + "car" + " must be a list: " + lispid2string( (id1))) + "\n"))
: 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && (
(id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))
>= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])))) + "\n")) : 0),
cons_cars[(((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && ((
(id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to "
+ "car" + " must be a list: " + lispid2string( (id1))) + "\n")) :
0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1))
>= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg "
+ 1 + " to " + "car" + " must be a list: " + lispid2string(
(id1))) + "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && ((
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])) - 1000]))) && ( (((!(intp(
(((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) && ( (((!(intp( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) >= 1000 && (( (((!(intp(
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) - 1000) < sizeof(cons_cars))
? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 &&
(( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to
" + "car" + " must be a list: " + lispid2string( (id1))) + "\n"))
: 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && (
(id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))
>= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])))) + "\n")) : 0),
cons_cars[(((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && ((
(id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to "
+ "car" + " must be a list: " + lispid2string( (id1))) + "\n")) :
0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1))
>= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg "
+ 1 + " to " + "car" + " must be a list: " + lispid2string(
(id1))) + "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && ((
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])) - 1000]))) >= 1000 && ((
(((!(intp( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && ((
(id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to "
+ "car" + " must be a list: " + lispid2string( (id1))) + "\n")) :
0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1))
>= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg "
+ 1 + " to " + "car" + " must be a list: " + lispid2string(
(id1))) + "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && ((
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) && ( (((!(intp( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) >= 1000 && (( (((!(intp(
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) - 1000) < sizeof(cons_cars))
? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 &&
(( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to
" + "car" + " must be a list: " + lispid2string( (id1))) + "\n"))
: 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && (
(id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))
>= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])))) + "\n")) : 0),
cons_cars[(((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && ((
(id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to "
+ "car" + " must be a list: " + lispid2string( (id1))) + "\n")) :
0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1))
>= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg "
+ 1 + " to " + "car" + " must be a list: " + lispid2string(
(id1))) + "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && ((
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])) - 1000]))) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (((!(intp( (((!(intp( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) && ( (((!(intp( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) >= 1000 && (( (((!(intp(
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) - 1000) < sizeof(cons_cars))
? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 &&
(( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to
" + "car" + " must be a list: " + lispid2string( (id1))) + "\n"))
: 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && (
(id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))
>= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])))) + "\n")) : 0),
cons_cars[(((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && ((
(id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to "
+ "car" + " must be a list: " + lispid2string( (id1))) + "\n")) :
0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1))
>= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg "
+ 1 + " to " + "car" + " must be a list: " + lispid2string(
(id1))) + "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && ((
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])) - 1000])))) + "\n")) : 0),
cons_cars[(((!(intp( (((!(intp( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1))
&& ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))
>= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars))

18
I optimized my code by implementing those [..] functions as macros- ünlü son sözler ...
BlueRaja - Danny Pflughoeft

3
Postscript tercümanımın ilk versiyonlarında benzer istismarlar yaptım. Push ve pop, makro olması gereken çok önemli işlevlerdi . Ancak, bunlardan birden fazlasını içeren bir ifade oluşturmak, tanımlanmamış davranışa yol açar. Tanımlanmamış davranış yalnızca -O3'te derlenirken yakalanır. Ve -O3'te fonksiyon versiyonları yine de inline olurdu.
luser droog

29

Bir keresinde bir C uygulamasını unix'ten pencerelere taşımak zorunda kaldım, bunun özel doğası suçluyu korumak için isimsiz kalacaktı. Bunu yazan adam üretim kodu yazmaya alışık olmayan bir profesördü ve açıkça başka bir dilden C'ye gelmişti. İnsanların çoğundan geldiği ülke oldukça iyi konuşsa da, İngilizce ilk dili değildi.

Uygulaması, C dilini daha iyi anlayabileceği bir formata çevirmek için ön işlemciyi yoğun bir şekilde kullandı. Ancak en çok kullandığı makrolar, aşağıdakileri içeren 'Thing.h' (ciddi olarak) başlık dosyasında tanımlandı:

#define I  Any void_me
#define thou  Any void_thee
#define iam(klas)  klas me = (klas) void_me
#define thouart(klas)  klas thee = (klas) void_thee
#define my  me ->
#define thy  thee ->
#define his  him ->
#define our  my methods ->
#define your  thy methods ->

... daha sonra aşağıdaki gibi canavarlıklar yazıyordu:

void Thing_setName (I, const char *name) {
iam (Thing);
if (name != my name) {
    Melder_free (my name);
    my name = Melder_wcsdup (name);
    }
    our nameChanged (me);
}

void Thing_overrideClass (I, void *klas) {
iam (Thing);
my methods = (Thing_Table)klas;
if (! ((Thing_Table) klas) -> destroy)
    ((Thing_Table) klas) -> _initialize (klas);
}

Tüm proje (~ 60.000 LOC) benzer bir tarzda yazılmıştır - marco cehennem, garip isimler, Olde-İngilizce jargon, vb. daha hızlı.

(Ben kopyalanıp ben aslen yapılmış bu cevabı kaydetmiştiniz bu soru üzerine ).


3
Oldukça iyilik ve arkaik İngilizce tarafından büyüleniyorum, elbette tüm kod korkunç görünüyor katılıyorum.
Darius Bacon

27

Karşılaştığım en kötü şey, belirlenen teknik liderin kütüphaneleri anlayamadığı bir yürütülebilir dosyalar paketi içeren bir üründü.

Bunun yerine, birkaç Visual Source Safe klasöründe paylaşılan dosya kümeleri vardı. Daha sonra her uygulama için biraz farklı davranmaları gerektiğini fark etti.

Burada uygulayabileceğiniz birkaç yeniden düzenleme adımı var.

Bunun yerine # ifdefs kullandı

   void DisplayLoadError()
   {
   #if defined __TIMETABLE_EDITOR
   MessageBox("Timetable Editor failed to load the correct timetable", MB_ERROR);
   #else if defined __SCHEDULESET_EDITOR
   MessageBox("Schedule Set Editor faied to load the correct Schedule Set", MB_ERROR);
   #else if defined __ROSTER_EDITOR
   MessageBox("Roster Editor failed to load the correct Roster", MB_ERROR);
   #endif
   }

17

Ağ üzerinden iletilen iletiler için benzersiz kimlik oluşturmak üzere LINE önişlemcisinin kullanımı:

NetworkMessages.h

#define MSG_LOGIN  __LINE__
#define MSG_LOGOUT __LINE__
#define MSG_CHAT   __LINE__

Bu, makronun makro olmayan bir çözümden gerçekten daha iyi olduğu bir örnektir:

Makro olmayan bir çözüm sınıfında, iletinin kimliğini izlemek için işlevler ve değişkenler oluşturulmalıdır. Geliştirici, ileti kimliği izlemeyi karmaşık hale getirebilir veya getirmeyebilir, ancak bunun okunması ve hata ayıklaması daha kolaydır.

Buna ek olarak, mesajı kaynağa ekleyerek yeni mesajlar eklemek daha kolaydır.

Bu durumun dezavantajı, dosyanın iletileri kullanan tüm koda eklenmesi gerektiğidir. Bir ileti düzenlendiğinde derleme süresi artar.


8
Ve sürümler birbiriyle uyumsuz olabilir (iyi değil!). Nasıl bir numaralandırma yeterli değildi?
Strager

Hem bu hem de Enum tam olarak aynı uyumsuzluk sorununa sahiptir.
MrValdez

17
Şimdi gelip # tanımları sıralıyorum ... ve protokol değişir. Ya da Doxygen dinini alıyorum ve tüm mesaj kodlarını belgeliyorum ve protokol değişiyor. En azından bir enum, ikinci değişiklik altında stabildir.
RBerteig

3
@MrValdez, bir numaralandırma bloğunu sırayla tutmak, dosya başlangıcına göre aynı satırlarda tanımları tutmaktan daha az kısıtlayıcıdır.
peterchen

Bunun eski bir yazı olduğunu biliyorum, ama bu işe yarıyor mu? Yani #define sadece mesaj sabitlerini LINE olarak değiştirecek ve o zaman LINE satır numarasına genişletilecek, bu yüzden farklı satırlarda aynı sabiti her kullandığımızda - değişecek (mevcut satır numarasına)?
XzKto

16

Oldukça kötü bir örnek:

#ifdef __cplusplus
#define class _vclass
#endif

Bu, bir classC ++ derleyicisi tarafından işlenmek üzere çağrılan bir üye değişkeni içeren bir C yapısına izin verir . İçinde bu yapıya sahip iki başlık vardır; bunlardan biri sonunda '#undef sınıfı' içeriyor, diğeri de yok.


1
Bu yüzden Objective-C @classyerine kullanır class.

14

Uluslararası Gizli C Kodlama Yarışması'nın bir yılında, tüm programın yapıldığı bir giriş vardı:

P

Tanımlayabileceğiniz şartla P , makefile'da istediğiniz herhangi bir program olarak .

Hatırladığım gibi, kategorilerden birinde kazandı ve ertesi yıl bu giriş tarzına izin vermemek için bir kural ortaya çıktı.

(Düzenleme: altı ay sonra ya da bir şey ... Eminim bunu yazarken "Hayır IOCCC" şey ana soru değildi ...)


12

Bir gün sıkıldım ve Objective-C'de bloklarla oynuyordum ...

#define Lambda(var, body) [^ id(id (var)) { return (body);} copy]
#define Call(f, arg) ((id(^)(id))(f))(arg)
#define Int(num) [NSNumber numberWithInteger:(num)]
#define Mult(a, b) Int([(a) integerValue] * [(b) integerValue])
#define Add(a, b) Int([(a) integerValue] + [(b) integerValue])
#define Sub1(n) Int([(n) integerValue] - 1)
#define Add1(n) Int([(n) integerValue] + 1)
#define If(cond, thenblock, elseblock) ([(cond) integerValue] ? (thenblock) : (elseblock))
#define Cons(car, cdr_) [[ConsType alloc] initWithCar:(car) cdr:(cdr_)]
#define Car(list) [(list) car]
#define Cdr(list) [(list) cdr]
#define Define(var, value) id var = (value)
#define Nullq(value) Int(value == nil)

"ilginç" şeylere izin vermek:

Define(Y, Lambda(f, Call(Lambda(x, Call(x, x)),
                         Lambda(x, Call(f, Lambda(y, Call(Call(x, x), y)))))));
Define(AlmostTotal, Lambda(f, Lambda(list, If(Nullq(list), Int(0),
                                              Add(Car(list), Call(f, Cdr(list)))))));
Define(Total, Call(Y, AlmostTotal));
Print(Call(Total, Cons(Int(4), Cons(Int(5), Cons(Int(8), nil)))));

(kısalık amacıyla bazı işlev ve sınıf tanımları gösterilmemiştir)


"Bir gün sıkıldım" ünlü geliştirici son sözler :)
Richard J. Ross III

11

Gördüğüm en kötü olanı olmayan :-)

Birisi bir yöntemin içine bir strcpy (sanırım bu 10 yıldan fazla bir süre önce) işlevini yazdı (çünkü strcpy ... iç çağıran yükünü istemiyorlardı).

Japonca karakterler için işe yaramayacağını ve ASCII veya Unicode'un başında bir "if" eklediklerini söylediler. Bu noktada kod bir ekran uzunluğundaydı ... büyük olasılıkla önbellek tutarlılığını öldürmek ve kodun satır içine alınması için sözde tasarruflarını silmek.

Kod türleri için aynı kaydetti (bu yüzden bir makro kullanmalıydım).

Elbette yazdıkları strcpy, standart kütüphanede bulunan elle ayarlanmış montajcıdan çok daha yavaştı ...

Tabii ki hepsini bir makro olarak yapmış olsalardı, bunun yerine strcpy çağrısı yapılabilirdi

Tabii şirketten ayrıldım (doğrudan bu yüzden değil ...)


The code was identical save for the types (so should have used a macro).Hayır, bir şablon kullanmalıydı.
BlueRaja - Danny Pflughoeft

1
Yerleşik strcpy'yi kullanmalıydı! (ve C kodu C ++ değildi, bu yüzden şablon yok) :-P
TofuBeer

Erken optimizasyon tüm kötülüklerin köküdür.
Hubert Kario

11

Zorunlu

#define FOR  for

ve

#define ONE  1
#define TWO  2
...

Kim biliyordu?


5
Ama-ama-ama KODDA YAZICI YOK! ;)
Bernard

onlar hala değişmez mon olabilir, alternatif sembol değil amaç / niyetle onları adlandırmalıdır. COBOL kodu Ben değişken 5 = 5 yaptıkları duydum sonra set 5 = 10 söyleyerek kod vardı ... var + 5 ve var + 10 aldıklarında gerçek sürpriz insanlar vardı
Greg Domjan

1
Bunu COBOL ile hiç duymadım, sadece FORTRAN ile. COBOL, elbette, ZERO, ZEROS ve ZEROES'a ayrılmış kelimeler olarak sahiptir, hepsi 0 ile aynı anlama gelir.
David Thornley

"#Define ONE 0" dan çok daha iyi. Bir kıkırdamak istiyorsanız, web'de bunu arayın ve sıfır olmayan isabet sayısıyla şaşırın.
Reuben

11
#define TRUE 0 // dumbass

Bunu yapan kişi birkaç yıl sonra kendini açıkladı - çoğu (hepsi değilse de) C kütüphanesi işlevleri her şeyin yolunda gittiğinin bir göstergesi olarak 0'a döner. Bu yüzden, aşağıdaki gibi kod yazabilmek istiyordu:

if (memcpy(buffer, packet, BUFFER_SIZE) == TRUE) {
; // rape that packet
}

Söylemeye gerek yok, ekibimizdeki hiç kimse (test veya geliştirici) koduna bir daha bakmaya cesaret edemedi.


1
0 "her şey yolunda" yapmak için C kütüphane işlevlerini suçluyorum: P
RCIX

6
Neden böyle bir şey açıklamıyorsunuz #define FLAG_SUCCESS 0?
pyon

11

Ben makrolarda gotos olan kodu korumak. Yani bir fonksiyonun sonunda bir etiket olacaktır fakat fonksiyon kodunda görünür bir gitme olmayacaktır. Daha da kötüsü, makro yatay olarak kaydırmadığınız sürece genellikle ekranın dışındaki diğer ifadelerin sonundadır.

#define CHECK_ERROR if (!SomeCondition) goto Cleanup

void SomeFunction() 
{ 
    SomeLongFunctionName(ParamOne, ParamTwo, ParamThree, ParamFour); CHECK_ERROR  
    //SomeOtherCode  
    Cleanup:    
   //Cleanup code  
}

Daha da kötüsü, makrolar hem gotoetiketlerin hem de hedef etiketlerin tanımlarının gizlenmesidir . Tamamen büyü.
08:24 reuben

Bundan acı çektim - ama makrolar fonksiyon çağrılarına benziyordu.
Jonathan Leffler

10
#include <iostream>
#define public_static_void_main(x) int main()
#define System_out_println(x) std::cout << x << std::endl

public_static_void_main(String[] args) {
  System_out_println("Hello World!");
}

3
Ve bir çalışma zamanı yazmak istedin. Ne kadar zaman kazandığımıza bak!
Bernard

4
@Trevor: Evet ... akıllı olanlar hala Java yapıyor. kapak için çalışır
Michael Myers

[] Öğesini daha önce yerine argümanlardan sonra koyarsanız ve "#define String int argc, char *" yazarsanız, derleme (ne yazık ki).
Adam Rosenfield

16
Diğerini daha çok seviyorum. Bu, birkaç makro ile Java'ya yakın bir şey yazıldığını gösterir. Diğeri, Java'nın çok sayıda gizli makro ve fonksiyon üyeli yapılarla yazıldığını gösterir. Birincisi ucuz bir şakaydı, ikincisi ayrıntılı ve iyi düşünülmüş bir şakaydı.
Chris Lutz

10

Sihirli sayılarla ilgili kuralları anlamayan bir sınıf arkadaşı tarafından:
#define TWO_HUNDRED_AND_EIGHTY_THREE_POINT_ONE 283.1


9

ASA - http://www.ingber.com/#ASA

Bunu takdir etmek için gerçekten indirmeniz gerekiyor. Tüm iş akışı makrolar tarafından belirlenir. Tamamen okunamıyor. Örnek olarak -

 if (asa_open == FALSE) {
asa_open = TRUE;
++number_asa_open;
#if ASA_PRINT
if (number_asa_open == 1) {
  /* open the output file */
#if USER_ASA_OUT
  if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {
#if ASA_SAVE
    ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "a");
#else
    ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "w");
#endif
  }
#else /* USER_ASA_OUT */
  if (!strcmp (ASA_OUT, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {
#if ASA_SAVE
    ptr_asa_out = fopen (ASA_OUT, "a");
#else
    ptr_asa_out = fopen (ASA_OUT, "w");
#endif
  }
#endif /* USER_ASA_OUT */
} else {
#if USER_ASA_OUT
  if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {
    ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "a");
  }
#else
  if (!strcmp (ASA_OUT, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {
    ptr_asa_out = fopen (ASA_OUT, "a");
  }
#endif
  fprintf (ptr_asa_out, "\n\n\t\t number_asa_open = %d\n",
           number_asa_open);
}
#endif /* ASA_PRINT */
} else {
++recursive_asa_open;
#if ASA_PRINT
if (recursive_asa_open == 1) {
  /* open the output file */
#if ASA_SAVE
#if USER_ASA_OUT
  if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {
    ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "a");
  }
#else
  if (!strcmp (ASA_OUT, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {
    ptr_asa_out = fopen (ASA_OUT, "a");
  }
#endif
#else /* ASA_SAVE */
#if USER_ASA_OUT
  if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {

vs vs.

Ve bu sadece seçenekleri ayarlamaktır. tüm program böyledir.


2
Aman tanrım ... Sanırım başım dönüyor.
Michael Foukarakis
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.