您遇到的最糟糕的 现实世界宏/预处理器滥用是什么(请不要设想IOCCC答案*哈哈*)?
如果它真的很有趣,请添加一个简短的片段或故事.目标是教一些东西,而不是总是告诉人们"永远不要使用宏".
ps:之前我曾经使用过宏...但是当我有一个"真正的"解决方案时,我最终会摆脱它们(即使真正的解决方案是内联的,它也会变得类似于宏).
额外:举一个例子,宏实际上比非宏解决方案更好.
相关问题: C++宏什么时候有用?
从内存来看,它看起来像这样:
#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,它有语法着色!)
他是一名俄罗斯程序员,主要从事汇编语言工作.他很想保存尽可能多的字节,因为他之前曾在内存非常有限的系统上工作过."它用于卫星.只有非常少的字节,因此我们将每个字节用于许多事情." (比特摆弄,重复使用机器指令字节的数值)当我试图找出什么样的卫星时,我只能得到"轨道卫星.用于制造轨道."
他还有另外两个怪癖:一个凸面镜子安装在他的显示器上方"为了知道谁在看",偶尔突然从椅子上退出,快速做十次俯卧撑.他将最后一个解释为"编译器在代码中发现错误.这是惩罚".
我最坏的:
#define InterlockedIncrement(x) (x)++ #define InterlockedDecrement(x) (x)--
我花了两天时间追踪一些多线程COM引用计数问题,因为有些白痴把它放在头文件中.我不会提到我当时工作的公司.
这个故事的寓意?如果您不了解某些内容,请阅读文档并了解相关信息.不要只是让它消失.
#define ever (;;) for ever { ... }
#include#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!"); }
挑战:任何人都可以用更少的定义和结构来做到这一点吗?;-)
#define private public
#define if while
这是对某人玩的笑话,受到影响的人并没有发现有趣
可怕的:
#define begin { #define end } /* and so on */
说真的,如果你想在Pascal中编码,买一个Pascal编译器,不要破坏漂亮的C语言.
一个'建筑师',非常谦虚的家伙,你知道这种类型,有以下几点:
#define retrun return
因为他喜欢快速打字.这位大脑外科医生曾经喜欢对比他聪明的人(这几乎是每个人)大声喊叫,并威胁要在他们身上使用黑带.
真实世界?MSVC在minmax.h中有宏,称为max
和min
,每次打算使用标准std::numeric_limits
函数时都会导致编译器错误.
Pascal语法和法语关键字之间的混合:
#define debut { #define fin } #define si if( #define alors ){ #define sinon }else{ #define finsi }
Raymond Chen 对使用流控制宏有很好的帮助.他最好的例子是直接来自最初的Bourne shell源代码:
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 }
我想为比赛提交一个名为chaos-pp的gem ,它通过预处理器宏实现一种函数式语言.
其中一个例子是完全由预处理器计算第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; }
直接来自Qt:
#define slots /* */ #define signals /* */
真的很高兴与其他libs作为boost :: signals进行交互......举个例子,Qt中还有许多其他人可以创建有趣的代码,例如:
class X : public QObject { Q_OBJECT private slots: //... public signals: //... };
这就是C++ ......但突然间:
boost::signals::trackable
不再是有效的C++.
Windows.h有很多滥用宏的函数.
MrValdez对Windows.h中的GetObject宏感到恼火
GetObject宏将GetObject()函数更改为GetObjectA()或GetObjectW()(取决于构建是否分别以非unicode和unicode编译)
MrValdez讨厌在GetObject功能行之前做的事情
#undef GetObject Object *GetObject()
另一种方法是将函数名称更改为GetGameObject()之类的其他名称
评论中的jdkoftinoff已经指出:问题是所有的Windows API函数都是宏.
Adam Rosenfield提到可以通过在包含windows.h来删除问题之前定义NOGDI,WIN32_LEAN_AND_MEAN,NOMINMAX等来解决问题.
#define return if (std::random(1000) < 2) throw std::exception(); else return
这真是太邪恶了.它是随机的,这意味着它会一直在不同的地方触发,它会改变return语句,它通常会有一些代码可能会自动失败,它会改变无辜的关键字,你不会对它产生怀疑并使用它来自标准空间的异常,因此您不会尝试搜索您的来源以找到它的来源.太棒了
一位同事和我在我们的一些代码流中发现了这两个宝石.这些宏在每个执行流式传输的SINGLE类文件中实例化.这个可怕的代码不仅遍布我们的代码库,当我们找到关于它的原始作者时,他在我们的内部维基上写了一篇7页的文章,捍卫这是完成他在这里尝试做的唯一可能的方法.
不用说,它已被重构,不再用于我们的代码库.
不要被突出显示的关键字抛弃.这是一个宏
#define DECLARE_MODIFICATION_REQUEST_PACKET( T ) \ namespace NameSpace \ { \ \ class T##ElementModificationRequestPacket; \ } \ \ DECLARE_STREAMING_TEMPLATES( IMPEXP_COMMON_TEMPLATE_DECLARE, NameSpace::ElementModificationRequestPacket, OtherNameSpace::NetPacketBase ) \ DLLIMPEXP_COMMON_TEMPLATE_DECLARE( NameSpace::ElementModificationRequestPacket ) \ DECLARE_AUTOGENERATION_TEMPLATES( DLLIMPEXP_COMMON_TEMPLATE_DECLARE, NameSpace::T##ModificationRequestPacket, NameSpace::ElementModificationRequestPacket ) \ \ namespace NameSpace { \ class DLLIMPEXP_COMMON T##ModificationRequestPacket : public ElementModificationRequestPacket \ { \ public: \ T##ModificationRequestPacket( NetBase * pParent ) \ : ElementModificationRequestPacket ( pParent ), m_Gen() {} \ \ T##ModificationRequestPacket( NetBase * pParent, \ Action eAction, \ const T & rT ) \ : ElementModificationRequestPacket ( pParent, eAction, rT ), m_Gen() {} \ \ T##ModificationRequestPacket( const T##ModificationRequestPacket & rhs ) \ : ElementModificationRequestPacket ( 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 m_Gen; \ \ friend class OtherNameSpace::StreamingBase::StreamingClassInfoT ; \ OtherNameSpace::StreamingBase::Streaming > m_Stream; \ \ }; \ } \ DLLIMPEXP_COMMON_TEMPLATE_DECLARE( ThirdNameSpace::ListenerBase ) \ DLLIMPEXP_COMMON_TEMPLATE_DECLARE( ThirdNameSpace::BroadcasterT ) \ typedef ThirdNameSpace::BroadcasterT T##ModifiedBroadcaster; #define IMPLEMENT_MODIFICATION_REQUEST_PACKET( T ) \ DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE( NameSpace::ElementModificationRequestPacket ) \ DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE( ThirdNameSpace::ListenerBase ) \ DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE( ThirdNameSpace::BroadcasterT ) \ INSTANTIATE_STREAMING_TEMPLATES( DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE, NameSpace::ElementModificationRequestPacket , OtherNameSpace::NetPacketBase ) \ INSTANTIATE_AUTOGENERATION_TEMPLATES( DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE, NameSpace::T##ModificationRequestPacket, NameSpace::ElementModificationRequestPacket )
更新(2009年12月17日):
关于这个可怕的宏观作者的更多好消息.截至8月,负责这种怪物的员工被解雇了.
I did the following myself, and I think I learned something from it.
In 1992 or so I wrote a small Lisp interpreter. It wasn't implemented in normal C, but in an interpreted C-like language. This C-like language used the standard C pre-processor, though.
The Lisp interpreter of course contained the functions car, which is used in Lisp to return the first element in a list, and cdr, which returns the rest of the list. They were implemented like this:
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 */
(Data were stored in arrays, since there were no structs. CONS_OFFSET is the constant 1000.)
car and cdr are used frequently in Lisp, and are short, and since function calls weren't very fast in the implementation language, I optimized my code by implementing those two Lisp functions as macros:
#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 checks that its argument actually is a list, and since that one is also used frequently in the interpreter, and is short, I wrote that one too as a macro:
#define CHECK_CONS(fun, pos, arg) \ (!IS_CONS(arg) ? \ LISP_ERROR("Arg " + pos + " to " + fun + \ " must be a list: " + lispid2string(arg)) : 0)
IS_CONS and LISP_ERROR were also used frequently, so I made them into macros too:
#define IS_CONS(id) \ ( intp(id) && (id) >= CONS_OFFSET \ && ((id) - CONS_OFFSET) < sizeof(cons_cars)) #define LISP_ERROR(str) (throw((str) + "\n"))
Seems reasonable?
But then, why did the entire system crash on this line:
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))
我曾经不得不将一个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)是用类似的风格写的 - 马克地狱,奇怪的名字,Olde-English行话等等.幸运的是我们能够抛出代码,因为我找到了一个执行相同算法的OSS库几十个时间更快.
(我复制并编辑了我最初在这个问题上做出的答案).
我遇到的最糟糕的事情是在一个包含一套可执行文件的产品中,指定的技术负责人没有找到库.
相反,他有几组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 }
使用LINE预处理器为通过网络传递的消息生成唯一ID:
NetworkMessages.h #define MSG_LOGIN __LINE__ #define MSG_LOGOUT __LINE__ #define MSG_CHAT __LINE__
这是宏实际上比非宏解决方案更好的示例:
在非宏解决方案类中,必须构建函数和变量以跟踪消息的ID.开发人员可能会或可能不会使消息ID跟踪变得复杂,而这更容易阅读和调试.
此外,只需将消息添加到源中,就可以更轻松地添加新消息.
这种情况的缺点是文件必须包含在使用消息的所有代码中.编辑消息时,编译时间会增加.
一个相当糟糕的例子:
#ifdef __cplusplus #define class _vclass #endif
这允许包含被调用的成员变量的C结构class
由C++编译器处理.这个构造有两个标题; 其中一个最后还包含'#undef class',另一个则没有.
在国际混淆C编码竞赛的一年中,有一个条目,整个程序是:
P
条件是你可以P
在makefile中定义你想要的任何程序.
我记得,它赢得了其中一个类别,并且在接下来的一年中出现了违反这种进入方式的规则.
(编辑:六个月后或者其他什么......我确信当我写这篇文章时,"没有IOCCC"的事情不在主要问题中......)
有一天我很无聊,在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)))));
(为简洁起见,未显示某些功能和类定义)
我看到的最糟糕的是不使用:-)
有人在一个方法中写了一个strcpy(我认为就是10多年前的那个)函数(因为他们不想要调用strcpy ...... sigh的开销).
他们发现它不适用于日文字符,所以他们在开始时添加了一个"if"来做ASCII或Unicode.在那时,代码大约是一个屏幕长...可能会杀死缓存一致性并删除他所谓的代码内联的节省.
除了类型之外,代码是相同的(所以应该使用宏).
当然,他们编写的strcpy比标准库中的手动调制汇编程序慢得多......
当然,如果他们刚刚将它作为一个宏完成,它可以被替换为strcpy的调用......
当然我退出了公司(不是直接因为......)
必须的
#define FOR for
和
#define ONE 1 #define TWO 2 ...
谁知道?
我维护在宏中有代码的代码.因此,函数最后会有一个标签,但在函数代码中没有可见的goto.更糟糕的是,除非您水平滚动,否则宏通常在屏幕外的其他语句的末尾.
#define CHECK_ERROR if (!SomeCondition) goto Cleanup void SomeFunction() { SomeLongFunctionName(ParamOne, ParamTwo, ParamThree, ParamFour); CHECK_ERROR //SomeOtherCode Cleanup: //Cleanup code }
#define TRUE 0 // dumbass
这样做的人在几年后解释了自己 - 大多数(如果不是全部)C库函数返回0表示一切顺利.所以,他希望能够编写如下代码:
if (memcpy(buffer, packet, BUFFER_SIZE) == TRUE) { ; // rape that packet }
毋庸置疑,我们团队中的任何人(测试人员或开发人员)都不敢再次浏览他的代码.
#include#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!"); }
由一位未能理解魔法数字规则的同学:
#define TWO_HUNDRED_AND_EIGHTY_THREE_POINT_ONE 283.1
ASA - 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 {
等等
这就是设置选项.整个计划就是这样.
曾经是编码员的"技术经理"将以下精彩的宏引入我们的C++项目,因为他认为NULL
在DOM解析例程中检查值太多了:
TRYSEGV CATCHSEGV
在封面下,这些使用了setjmp
,longjmp
和一个信号处理程序,SIGSEGV
以模拟"捕获"段错误的能力.
当然,一旦代码退出原始TRYSEGV
宏调用的范围,代码中的任何内容都不会重置跳转指针,因此代码中的任何段错误都将返回到(现在无效)jump_env
指针.
代码会立即死在那里,但在破坏程序堆栈和渲染调试之前或多或少没有意义.
AI Game Programming Wisdom有一章,其中宏用于为有限状态机创建脚本语言.
由于书籍和代码是受版权保护的材料,因此这里是指向详细说明宏的页面的Google书籍链接(最终的脚本语言可以在第324页找到.)
在Lucent,我曾经看过Steve Bourne原始Unix shell的源代码,并发现他使用C预处理器使C看起来像Pascal或 Algol.处理if语句的部分如下所示:
#define IF if ( #define THEN ) { #define ELSE } else { #define ELIF } else if ( #define FI ; }
我的一个朋友告诉我,他在20世纪90年代中期对它进行了一些维护,但情况仍然如此.(这里有一个关于代码库固有保守性的教训.)
当然,史蒂夫在早期做过这个实验,如果他以后写的话,我肯定会有第二个想法.
更新:根据维基百科的Bourne Shell文章,这些宏给它带来了Algol 68的味道.并且,完整的宏集在这里!他们显然影响了国际混淆C代码竞赛的创始人.
我喜欢这个例子,它使用宏来估计PI的值.圆越大,近似越精确.
#define _ -F<00||--F-OO--; int F=00,OO=00;main(){F_OO();printf("%1.3f\n",4.*-F/OO/OO);}F_OO() { _-_-_-_ _-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_ _-_-_-_ }
另一个是该c
计划
c
要编译,您需要定义c
为
-Dc="#includeint main() { char *t =\"Hello World\n\"; while(*t) putc(*t++, stdout); return 0; }"
C.的Coroutines(AKA Stackless线程):)这是邪恶的诡计.
#define crBegin static int state=0; switch(state) { case 0: #define crReturn(i,x) do { state=i; return x; case i:; } while (0) #define crFinish } int function(void) { static int i; crBegin; for (i = 0; i < 10; i++) crReturn(1, i); crFinish; } int decompressor(void) { static int c, len; crBegin; while (1) { c = getchar(); if (c == EOF) break; if (c == 0xFF) { len = getchar(); c = getchar(); while (len--) crReturn(c); } else crReturn(c); } crReturn(EOF); crFinish; } void parser(int c) { crBegin; while (1) { /* first char already in c */ if (c == EOF) break; if (isalpha(c)) { do { add_to_token(c); crReturn( ); } while (isalpha(c)); got_token(WORD); } add_to_token(c); got_token(PUNCT); crReturn( ); } crFinish; }
switch (device_id) { #ifndef PROD_1 #ifndef PROD_2 #ifdef PROD_3 case ID_1: #endif #ifdef PROD_4 #ifdef PROD_5 case ID_2: case ID_3: case ID_4: #elif defined(PROD_4) #ifndef PROD_6 case ID_1: #endif // PROD_6 case ID_5: #endif case ID_6: #endif #ifdef PROD_7 #ifndef PROD_8 case ID_7: #endif #endif
(名称改为保护不那么无辜)
请注意,我们还没有得到任何代码,这只是为了获得第一个实际的代码位.这实际上发生了(几乎,但不完全相同的方式)几个函数,每个函数最终只有4种可能的变化(也主要是复制/粘贴,有轻微的变化和#ifdefs自己的).