あなたが今まで遭遇した中で最悪の実世界のマクロ/プリプロセッサの乱用は何ですか?


176

これまでに遭遇した中で最悪の 現実のマクロ/プリプロセッサの乱用は何ですか(不自然なIOCCCが* haha​​ *に回答しないでください)?

本当に面白い場合は、短いスニペットまたはストーリーを追加してください。目標は、常に「マクロを使用しない」ことを人々に教えるのではなく、何かを教えることです。


ps:以前にマクロを使用したことがありますが、通常は「実際の」ソリューションがあるときに最終的にそれらを削除します(実際のソリューションがインライン化されてマクロに似ている場合でも)。


おまけ:マクロがマクロ以外のソリューションよりも本当に優れていた例を挙げてください。

関連質問: C ++マクロはいつ有益ですか?


マクロの手で私が受けた蔓延している虐待に注意を向けるための+1。
i_am_jorf 2009年

37
#define true false //幸せなデバッグ:)
n0rd

コミュニティウィキとは、この質問またはその回答に対する賛成/反対票から誰も評判を得ない(または失う)ことを意味します。多くの人々は、このような質問を評判を得るための安くて簡単な方法であると見なしています。そのため、コミュニティウィキとしてマークを付けると、すべての人々が形を崩して閉じてしまう可能性が低くなります。
Graeme Perrow

2
「人々はすべて形が崩れ、それを閉じる可能性が高い」:スタックオーバーフローでユーモラス/面白いコンテンツを望まないことを意味していますか?
Trevor Boyd Smith、

2
簡単に言えば、プリプロセッサは言語の一部であるため、他のものと同じように、使用するのは悪/悪ではありません。
Mr. Boy

回答:


410

メモリからは、次のように見えました。

#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)

はい、その通りです。関数の中で中括弧はありません。構文の強調表示はめちゃくちゃだったので、viを使用して編集しました(vimではなく、構文の色付けがされています!)

彼はほとんどがアセンブリー言語で働いていたロシアのプログラマーでした。以前は非常に限られたメモリのシステムで作業していたため、彼はできるだけ多くのバイトを節約することに熱狂的でした。「それは衛星用でした。ごくわずかのバイトなので、多くのことのために各バイトを使います。」(ビットをいじり、数値に機械命令バイトを再利用)どんな種類の衛星を調べようとしたところ、「軌道衛星。軌道に乗るために」しか得られませんでした。

彼には他に2つの癖がありました:モニターの上に「誰が見ているかを知るため」に取り付けられた凸面鏡と、時折突然椅子から出て急いで10回腕立てをしました。彼はこれを「コンパイラがコードにエラーを見つけた。これは罰だ」と説明した。


87
「コンパイラはコードにエラーを見つけました。これは罰です。」!! 会社はあなたを見つけました...仲間の従業員への罰!
学習

227
ソビエトロシアでは、プログラムはあなたをコンパイルします!
Crashworks、

53
コンパイラのエラー「罰」について読んだとき、私が最初に思ったのは「ドビーは手をアイロンをかけなければならない」ということでした。
Graeme Perrow

124
コンパイラー(私も含む)は、コンパイラーがコードでエラーを検出するたびにすべてのプッシュアップを10回実行すると、はるかに適していると思います。これにより、コンパイルによるテストの発生を減らすこともできます。
MikeyB 2009年

5
その男は素晴らしいですね。しかし、そうです、これがどのようにコードサイズを改善することになっているのかはわかりません。
2009

274

私の最悪:

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

一部のばか者がこれをヘッダーファイルに入れたため、マルチスレッドのCOM参照カウントの問題を追跡するのに2日間費やしました。当時働いていた会社については触れません。

この話の教訓は?何かが分からない場合は、ドキュメントを読んで理解してください。消え去るだけではいけません。


146
@ジョシュア:このコードをマルチスレッド環境で実行すると、意図せずにそれが実行される可能性があります
1800情報

11
「何かが分からない場合は、ドキュメントを読んで、それについて学んでください。単にそれを片付けないでください。」-アメン!
ポールアレクサンダー

2
@ 1800情報:投票権を失うだけだと思う​​ので、投票できません; p
wkf '25

5
C ++以外のプログラマーとして私を許してください:ここでの主な問題は、スレッドセーフな関数が非スレッドセーフな関数に変換されることですか?または、InterlockedIncrementはポインターを期待しているので、ポインターが指しているのではなく、ポインターを増やします。または両方?
Tim Pietzcker

38
問題は、通常、InterlockedIncrementがWindows APIで定義されたアトミック関数であることです。したがって、人々がInterlockedIncrementを呼び出すとき、アトミックに実行されることが保証されている関数を呼び出すことを期待します。代わりに、誰かが同じ名前のマクロを定義しました。これは、単純で非原子的な増分に評価されます
jalf

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

52
私は<#define forever for(;;)>を好むので、<forever {...}>を書くことができます
paxdiablo 2009年

私が今までに失った痕跡を
残し

6
Paxの提案はK&Rから直接得たものではありませんか?それでも、努力する価値はないと思います。
ジョンエリクソン

それは実際にはまったく悪いことではありません。私はfor (;;)イディオムを使用していません。それ以外の場合は、すぐにこのマクロをコードに追加します。
AnT 2009年

1
@hayalci:ではEmacs Lispに(と一部のCommon Lispの実装)あなたは可能性に(defmacro ever ())して、(require 'cl (ever))
ジョー・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!");
}

課題:定義と構造体を減らして誰でもそれを実行できますか?;-)


19
あなたはjava-to-cコンバーターを書いたところです!ホレイ!
Andreas Petersson

25
「攻撃的」と報告されています。(私は子供です!)
Annika Backstrom

40
それは恐ろしく美しいか美しく恐ろしいです。
Chris Lutz、

38
@ Mark-として宣言しpublicstatic as nothing, void`としてint、そしてmain(x)as main()なので、にpublic static void main(String[] args)変わりint main()ます。次ににSystem変わりS s;s、がにSystem.out.println("Hello World!");変わり、がstruct内の構造体S s; s.out.println("Hello World!");println関数を呼び出します。FS
Chris Lutz、

2
これを見てください:mailcom.com/ioccc/chia/chia.c(ダウンロードしてコンパイルしてください)
Roberto Bonvallet

130
#define private public

私は以前にそれをしたことがあります。場合によっては、メンバー変数を変更したり、変更できないサードパーティのコードの関数をオーバーライドしたりする必要があるだけで、アクセサを提供していませんでした。
マイケルクリストフィク

30
ユニットテストでは、オブジェクトデザインのゴーストが夜間にあなたを悩ませますが、これは便利な場合もあります。
Epaga 2009年

12
うーん、未定義の動作、1つの定義のルールの簡単な違反、潜在的なレイアウトの違い。うん、これは勝者です。
David Thornley、

10
だから、私はプライベートのものとパブリックのものにアクセスできますが、保護されたものにはアクセスできませんclass。キーワードと最初のアクセス修飾子の間のものにはアクセスできません。
ケンブルーム

3
@ケン:#define class struct #define protected public
Yakov Galka

107
#define if while

それは誰かに冗談を言っていた、影響を受けた人たちが面白いとは思わなかった


22
#defineしている間は、もっと油断ならないでしょう。
starblue 2009年

7
あなたの声明を明確にすべきです。影響を受けた人々からは面白いとは言えませんでした。:-)
アンドリューシェパード

6
宿題をするとき、わざわざこういうことをしました。
ピョン2009

15
これは良いいたずらですが、「else」ステートメントがある場合はコンパイルされません。#define if(x)if(true)が最も効果的であることがわかりました。
グラフィックNoob、

32
私は常に#define sizeof(x)rand()を好んだ
Jon

106

恐ろしい:

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

真剣に、もしあなたがPascalでコーディングしたいなら、Pascalコンパイラを購入してください。美しいC言語を破壊しないでください。


45
さて、あなたは十分に巧妙なヘッダーファイルでどの言語をシミュレートできるのか疑問に思っています。
リザードを請求する

47
Cは美しくありません。それはむしろ醜いです。
rlbond 2009年

27
その美しさはそのシンプルさにあります。それは...アセンブリ言語の可読性と組み合わされたアセンブリ言語のすべての速度を持っていると言われています:-)私は肥大化したC ++よりもそれを好みます(私はその巨大なライブラリのために私の仕事ではJavaを好みますが)。
paxdiablo 2009年

9
いえいえ。ボーンシェルのボーンのオリジナルソースを見つけます。彼はある種の粗悪なALGOLのような混乱を得るためにまさにこれをしました。
RBerteig 2009年

3
#define DO for(int _i = 0; _i <= 1; ++ _ i){if(_i == 1)//// LINE BREAK ///// #define IF(cond); if(!(cond))break; } //// LINE BREAK //// DO printf( "a")IF(1 == 2);
Adrian Panasiuk、2009

93

「建築家」、非常に謙虚な男、あなたはタイプを知っています、次のものを持っていました:

#define retrun return

彼は速くタイプするのが好きだったので。脳外科医はかつて彼より頭が良い人(ほとんど全員)を怒鳴りつけ、黒帯をかけると脅迫していた。


私は実際にそれを考えたので、私はそのタイプミスを作ります。
ジョシュア

4
むしろ、編集者にretrunを自動置換して元に戻すように教える。少なくとも、私のIRCクライアントに行われ、このようなhackeriesをIVE
Tetha

1
ねえ、私はかつてその「建築家」と一緒に働いていたと思います。エゴをなだめる必要があったとき、彼は結局、上級建築家に再分類されました。
BIBD 2009

1
タイプできず、 'rn'ニュースリーダーが起動してサーバーに接続するのに5分かかったため、bashで 'rn'を 'rm'に再定義しました。
Martin Beckett、

2
新しいターミナルを開いて(または別のvtに切り替えて)実行することはできませんkillall rnか?
Joe D

69

現実の世界?MSVCのminmax.hにはマクロと呼ばれるマクロがmaxありmin、標準std::numeric_limits<T>::max()関数を使用するたびにコンパイラエラーが発生します。


2
ああ、そうです。MS固有のヘッダーの後に、
正常

3
(std :: numeric_limits <T> :: max)()を使用して解決します。
rlbond 2009年

36
C / C ++-> Preprocessor-> Preprocessor DefinitionsのプロジェクトプロパティにNOMINMAXを追加します。
mattnewport 2009

18
これらのマクロは、最小および最大よりも長いMSヘッダーに存在し、C ++標準ライブラリにありました。
リチャード

4
他の4つの外部依存関係も、かっこ悪いマクロから適切に記述されたテンプレートに至るまで、さまざまな程度の独自の最小値/最大値を定義している場合、さらに悪いのです。またはそれ以外の場合はこれらをスキップします...私の本では、言語の50%が非難されています。
Roman Starkov、2010年

58

Pascal構文とフランス語のキーワードの組み合わせ:

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

36
#define zut_alors exit(-1)
MikeyB

4
それは素晴らしいです、そしてそれは私を大声で笑わせました。それで、これは基本的にCで実装されたローカライズされたフランス語のBasicバージョンですか?
ボビー

56

Raymond Chenは、フロー制御マクロの使用に反対しています。彼の最良の例は、元のBourneシェルのソースコードからの抜粋です。

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
2つのポイント:1つは、このペーストは元のインデントをめちゃくちゃにした。そして2つ目は、コードはそれが何であるかについては問題なく見えます。熱狂的なAlgol-68ファンによる1970年代のUnixC。ラッキースティフが奇抜なスタイルで自分を表現できるのに、なぜスティーブボーンができないのでしょうか。もちろん、Algol 68を知らない、それを維持することを非難された人は、自分の好みを広げるこの機会を認めないかもしれません。
ダライアスベーコン

これは、推奨されるプログラミングスタイルではなく、Steve Bourneによるジョークとして意図された可能性があると思います
Martin Beckett

2
私はif... else... elif... ficase... esac以前に(ボーンがshのために発明したまさにその言語で)見たことがありloopますpoolが、... は本物の宝石です。
ホブ、2011

54

コンテストに、プリプロセッサマクロを使用して関数型言語を実装するchaos-ppと呼ばれる宝石を提出したいと思います。

例の1つは、500番目のフィボナッチ数をプリプロセッサで完全に計算することです。

プリプロセッサの前の元のコードは次のようになります。

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

ファイルを前処理すると、次の結果が得られます(かなり長い待機の後)。

$ 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
CVSからコードを取得して確認できます。私はそれを偶然見つけたとき、それについていくつかの詳細を私のブログ記事に入れていました:bnpcs.blogspot.com/2009/02/… 結果のコードのデバッグに関する問題ではない場合(非常に長い行がある場合の問題)彼らはそのようなA「言語」)によって生成され、それは、Cのための実用的なコードジェネレータとしても使用可能だったかもしれない
アンドリューY

コンパイルに永遠にかかることを想像できます
Paul Fultz II、

52

Qtから直接:

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

boost :: signalsとして他のライブラリとやり取りするのは本当にいいことです...ほんの一例ですが、Qtには次のような面白いコードを作成する他の多くのものがあります。

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

そしてそれはC ++です...しかし突然:

boost::signals::trackable

もはや有効なC ++ではありません。


5
:)それは、他のライブラリを何の理由もなく壊すマクロです。それは私が予想したよりもさらに良いです:)
デビッド・ロドリゲス-dribeas

38
Qtは非常に領土が
広く

21
外のマクロを使用してその名前空間の悲しいQtの攻撃ライブラリ
デビッド・ロドリゲス- dribeas

7
幸い、boost ::
signals2によって

9
この相互作用を恐れている場合は、Q_SIGNALSおよびQ_SLOTSを使用してください。
Tadeusz A.Kadłubowski、2009

50

Windows.hには、マクロを悪用する多くの関数があります。


MrValdezは、Windows.hにあるGetObjectマクロに悩まされています

GetObjectマクロは、GetObject()関数をGetObjectA()またはGetObjectW()に変更します(ビルドがそれぞれ非ユニコードおよびユニコードでコンパイルされているかどうかによります)

MrValdezはGetObject関数行の前に行う必要があることを嫌っています

#undef GetObject

Object *GetObject()

代わりに、関数名をGetGameObject()などの他の名前に変更します。


コメントのjdkoftinoffはそれを釘付けにしました:問題はすべてのウィンドウAPI関数がマクロであることです。

Adam Rosenfieldは、問題を取り除くためにwindows.hをインクルードする前に、NOGDI、WIN32_LEAN_AND_MEAN、NOMINMAXなどを定義することで問題を修正できると述べました。


3
これを抑制できますが、windows.hをインクルードする前にNOGDIを#defineします。もちろん、さまざまなGDI関数を使用する必要はありません。WIN32_LEAN_AND_MEAN、NOMINMAXなど、他のものが定義または含まれるのを抑制するマクロが他にもたくさんあります。
Adam Rosenfield、

1
GetObjectはかなり一般的な関数名です。おそらく、衝突を回避するために、コンテキストにわかりやすい名前を付けることができます。しかし、それはかなり邪悪なマクロのケースです。
ストレッジャー2009年

1
win32にAPI名をFooAとFooWに変換するためのすべてのマクロがあることは非常に面倒です。SendMessageに問題があります。
i_am_jorf 2009年

6
問題は、すべてのWindows API関数がマクロであることです。私を悩ませたのは、GetTickCount()でした。私はほとんどのプログラミングをウィンドウの外で行っているので、ウィンドウのヘッダーですべての定義を見つけ、それらをすべて定義した独自のインクルードファイルを作成して、互換性を事前に確認しました。
jdkoftinoff 2009年

12
勝者はいると思います。それは現実の世界であり、途方もなく悪い考えであり、多くの無実のプログラマーに影響を与えています。マイクロソフトのこの宝石の責任者は誰でも戦争犯罪者と見なされるべきです...最良の部分は、GetObject、SendMessage、CreateWindowのような驚くほど一般的な名前を使用することを2度考えなかったことです。
2009

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

これはとても悪です。これはランダムです。つまり、常に別の場所で起動し、returnステートメントを変更します。通常、それ自体に何らかのエラーが発生する可能性のあるコードが含まれており、疑いを持たない無邪気に見えるキーワードを変更して使用します。 std spaceからの例外なので、ソースを検索してソースを見つけようとはしません。ただ素晴らしい。


4
これをテストしたところ、少なくともランダムのインクルードが欠落しているために、デフォルトではコンパイルできません。ただし、誤ってインクルードした場合、状況はさらに悪化します
-VC

大好きです!純粋な天才。このアプリケーションを他の人が管理していないときに「デバッグ」すると、見栄えがよくなると想像してください。
10

36

同僚と私は、オブジェクトストリーミングのコードの一部でこれら2つの宝石を見つけました。これらのマクロは、ストリーミングを行ったすべてのSINGLEクラスファイルでインスタンス化されました。この恐ろしいコードがコードベース全体に広がっただけでなく、元の作者にそれについて尋ねたとき、彼は私たちの内部ウィキに7ページの記事を書いて、ここでやろうとしていたことを達成する唯一の可能な方法としてこれを擁護しました。

言うまでもないことですが、それ以降はリファクタリングされ、コードベースでは使用されなくなりました。

ハイライトされたキーワードに惑わされないでください。これはすべてマクロです

#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> )

更新(2009年12月17日):

この恐ろしいマクロの作者に関するより良いニュース。8月の時点で、この怪物を担当した従業員が解雇されました。


3
「デバッグは最初のコードを書くより2倍難しいので、コードをできる限り巧妙に書くと、当然のことながら、デバッグするほど賢くありません。」
Trevor Boyd Smith

33

私は自分で次のことをしました、そしてそれから何かを学んだと思います。

1992年かそこらで、小さなLispインタプリタを書きました。これは通常のCでは実装されていませんが、インタープリターCのような言語で実装されています。ただし、このC言語に似た言語では、標準のCプリプロセッサが使用されていました。

当然のLispのインタプリタが関数に含まれるリストの最初の要素を返すためにLispで使用され、そしてCDRリストの残りを返します。彼らはこのように実装されました:

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 */

(構造体がないため、データは配列に格納されていました。CONS_OFFSETは定数1000 です。)

carcdrはLispで頻繁に使用され、短く、関数呼び出しは実装言語ではあまり高速ではなかったため、これら2つのLisp関数をマクロとして実装することでコードを最適化しました。

#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は、引数が実際にリストであることをチェックします。これは、インタプリタでも頻繁に使用され、短いため、マクロとしても記述しました。

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

IS_CONSLISP_ERRORも頻繁に使用されたので、これらもマクロにしました。

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

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

合理的なようです?

しかし、なぜこの行でシステム全体がクラッシュしたのですか。

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

問題を見つけるのに長い時間を費やしましたが、最終的には、その短い行がプリプロセッサーによって拡張されたものを確認しました。これは31370文字の行に拡張されましたが、ここではわかりやすくするために行(502行)に分割しています。

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-有名な最後の言葉...
BlueRaja-Danny Pflughoeft

3
私はPostscriptインタープリターの初期バージョンで同様の悪用を犯しました。プッシュとポップは、マクロであるべきほど重要な機能でした。ただし、これらを複数含む式を作成すると、動作が未定義になります。未定義の動作は、-O3でコンパイルするときにのみキャッチされます。そして、-O3では、関数のバージョンはとにかくインライン化されていました。
luser droog 2011

29

私はかつて、Cアプリケーションをunixからwindowsに移植しなければなりませんでした。その特定の性質は、罪を守るために名前を付けないままにしておきます。それを書いた人は、プロダクションコードを書くことに慣れていない教授で、明らかに他の言語からCに来ていました。また、英語が彼の第一言語ではなかったということも起こります。

彼のアプリケーションは、プリプロセッサを多用して、C言語をより理解しやすい形式に変換しました。しかし、彼が最も頻繁に使用したマクロは、「Thing.h」(真剣に)という名前のヘッダーファイルで定義されていました。

#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 ->

...それから彼は次のような怪物を書くために使用しました:

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);
}

プロジェクト全体(〜60,000 LOC)は、マルコの地獄、奇妙な名前、古い英語の専門用語など、同様のスタイルで記述されました。幸い、同じアルゴリズムを数十個実行するOSSライブラリを見つけたので、コードを破棄することができました倍の速さ。

(私は最初にこの質問で作成したこの回答をコピーして編集しました)。


3
私は所有格と古風な英語にどちらかと言えば魅力的です。もちろん、そのすべてがコードがひどいものに見えることに同意します。
ダライアスベーコン

27

私が今まで遭遇した中で最悪だったのは、指定された技術リーダーがライブラリを理解していなかった実行可能ファイルのスイートを含む製品でした。

代わりに、彼はいくつかのVisual Source Safeフォルダーで共有されるファイルのセットを持っていました。その後、アプリケーションごとに動作が少し異なる必要があることに気付きました。

ここで適用できるリファクタリングのステップがいくつかあります。

代わりに、彼は#ifdefsを使用しました

   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

LINEプリプロセッサを使用して、ネットワーク経由で渡されるメッセージの一意のIDを生成します。

NetworkMessages.h

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

これは、マクロが非マクロソリューションよりも優れている例です。

非マクロソリューションクラスでは、メッセージがどのIDであるかを追跡するために、関数と変数を作成する必要があります。開発者はメッセージIDの追跡を複雑にする場合とそうでない場合がありますが、これは読みやすくデバッグが簡単です。

さらに、メッセージをソースに追加するだけで、新しいメッセージを簡単に追加できます。

この状況の欠点は、メッセージを使用するすべてのコードにファイルを含める必要があることです。メッセージが編集されるたびに、コンパイル時間が長くなります。


8
また、バージョンは互いに互換性がない可能性があります(良くない!)。なぜ列挙型では不十分なのですか?
ストレッジャー2009年

これとEnumには、まったく同じ非互換性の問題があります。
MrValdez 2009年

17
次に、#definesを並べ替えて、プロトコルを変更します。または、Doxygenの信仰を得て、すべてのメッセージコードとプロトコルの変更を文書化します。後者の変更では、少なくとも列挙型は安定しています。
RBerteig 2009年

3
@MrValdez、列挙型のブロックを順番に保持する方が、ファイルの開始に関連して同じ行に定義を保持するよりも制限が少なくなります。
peterchen 2009年

これは古い投稿であることは知っていますが、これでも機能しますか?つまり、#defineはメッセージ定数をLINEに置き換えるだけで、LINEは行番号に展開されるため、異なる行で同じ定数を使用するたびに、(現在の行番号に)変更されますか?
XzKto 2012

16

かなり悪い例:

#ifdef __cplusplus
#define class _vclass
#endif

これにより、呼び出されたメンバー変数を含むC構造体をclassC ++コンパイラーで処理できるようになります。この構成要素が含まれている2つのヘッダーがあります。そのうちの1つは最後に「#undefクラス」も含み、もう1つは含みません。


1
これがObjective-Cがの@class代わりに使用する理由ですclass

14

国際難読化Cコーディングコンテストの1年間で、プログラム全体が次のようなエントリになりました。

P

ただしP、makefileで任意のプログラムを定義できます。

私が覚えているように、それはカテゴリーの1つで勝ちました、そして翌年、そのスタイルのエントリーを認めないルールが現れました。

(編集:6か月後か何か...私がこれを書いたとき、「No IOCCC」のことはメインの質問になかったと確信しています...)


12

私はある日退屈していて、Objective-Cでブロックをいじっていました...

#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)

次のような「興味深い」ものを許可する:

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)))));

(簡潔にするために、一部の関数とクラスの定義は表示されていません)


「私はいつか退屈した」有名な開発者の最後の言葉:)
リチャードJ.ロスIII

11

私が見た中で最悪のものは不使用でした:-)

誰かがメソッド内でstrcpy(これは10年以上前だったと思います)関数を記述しました(strcpyを呼び出すオーバーヘッドを望まないためです...ため息)。

彼らは、日本語の文字では機能しないと主張し、ASCIIまたはUnicodeを実行するために最初に「if」を追加しました。その時点で、コードは1画面分程度でした...キャッシュのコヒーレンシーを殺し、コードのインライン化のために想定されていた節約を消去する可能性があります。

コードは型を除いて同一でした(したがって、マクロを使用する必要がありました)。

もちろん、彼らが書いたstrcpyは、標準ライブラリにある手動で調整されたアセンブラよりもはるかに低速でした...

もちろん、それらをすべてマクロとして実行した場合は、strcpyの呼び出しに置き換えることができます...

もちろん、私は会社を辞めました(そのために直接ではありません...)


The code was identical save for the types (so should have used a macro).いいえ、彼はテンプレートを使用する必要がありました。
BlueRaja-Danny Pflughoeft、2011

1
彼は組み込みのstrcpyを使用するべきでした!(そしてそれはC ++ではなくCコードなのでテンプレートはありませんでした):-P
TofuBeer

時期尚早の最適化は、すべての悪の根源です。
Hubert Kario、2011

11

義務的

#define FOR  for

そして

#define ONE  1
#define TWO  2
...

誰かわかったね?


5
しかし、コードには文字はありません!;)
バーナード

それらはまだリテラルのmonであり、代替シンボルではなく目的/意図によってemに名前を付ける必要があります。私が聞いたCOBOLコードは変数5 = 5を作成し、後でset 5 = 10と言ったコードがありました... var + 5を実行してvar + 10を取得したときに
本当に驚いた人々

1
COBOLでは、FORTRANだけでそれを聞いたことはありません。COBOLは、当然のことながら、0とまったく同じことを意味し、それらのすべて、予約語としてZERO、ZEROS、ZEROESとを持っている
デヴィッド・ソーンリー

"#define ONE 0"よりもはるかに優れています。クスクス笑いしたい場合は、それをウェブで検索すると、0以外のヒット数に驚かされます。
ルーベン

11
#define TRUE 0 // dumbass

これを行った人は数年後に自分自身を説明しました-(すべてではないにしても)ほとんどのCライブラリ関数は、すべてがうまくいったことを示す0を返します。したがって、彼は次のようなコードを記述できるようにしたいと考えました。

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

言うまでもなく、私たちのチーム(テスターまたは開発者)の誰も、彼のコードをもう一度一瞥することはしませんでした。


1
私は0を「すべて大丈夫」にしたCライブラリ関数を非難します:P
RCIX 2010年

6
次のように宣言してみません#define FLAG_SUCCESS 0か?
pyon

11

マクロにgotoを含むコードを管理しています。したがって、関数の最後にはラベルが付けられますが、関数コードにはgotoは表示されません。さらに悪いことに、このマクロは、水平方向にスクロールしない限り、通常は他のステートメントの最後にあります。

#define CHECK_ERROR if (!SomeCondition) goto Cleanup

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

さらに悪いのは、マクロがgotoステートメントとターゲットラベルの定義の両方を非表示にする場合です。完全に魔法です。
ルーベン

私はそれに苦しんでいます-しかし、マクロは関数呼び出しのように見えました。
ジョナサンレフラー

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
そして、あなたはランタイムを書きたかったのです。どれだけの時間を節約できたか見てください!
バーナード

4
@Trevor:ええ...賢い人たちは今でもJavaをやっています。カバーの実行
マイケルマイヤーズ

以前にではなくargsの後に[]を置き、 "#define String int argc、char *"とすると、(悲しいことに)コンパイルされます。
アダムローゼンフィールド

16
私は他のほうが好きです。これは、いくつかのマクロを使用して記述されているJavaに近いものを示しています。もう1つは、大量の卑劣なマクロと関数メンバーを持つ構造体で記述された正確なJavaを示しています。最初のものは安い冗談でしたが、2番目のものは精巧で徹底した冗談でした。
Chris Lutz、

10

マジックナンバーに関するルールを理解できなかったクラスメートによって:
#define TWO_HUNDRED_AND_EIGHTY_THREE_POINT_ONE 283.1


9

として - http://www.ingber.com/#ASA

あなたはそれを感謝するためにそれをダウンロードする必要があります。ワークフロー全体はマクロによって決定されます。それは完全に読めません。例として-

 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 {

などなど

そして、それはオプションを設定するだけです。プログラム全体はそのようなものです。


2
なんてこった…めまいがしそうだ。
Michael Foukarakis、2010
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.