你所遇到的最糟糕的实际宏/预处理器滥用是什么(请不要回答显然的IOCCC*哈哈*)?
如果有一个有趣的小片段或故事,请添加进来。目标是教授一些东西,而不是总是告诉人们“永远不要使用宏”。
p.s .:我以前使用过宏……但通常我最终会摆脱它们,当我有了“真正的”解决方案时(即使真正的解决方案是内联的,因此类似于宏)。
奖励:给出一个示例,其中宏确实比非宏解决方案更好。
相关问题:C++宏何时有利?
你所遇到的最糟糕的实际宏/预处理器滥用是什么(请不要回答显然的IOCCC*哈哈*)?
如果有一个有趣的小片段或故事,请添加进来。目标是教授一些东西,而不是总是告诉人们“永远不要使用宏”。
p.s .:我以前使用过宏……但通常我最终会摆脱它们,当我有了“真正的”解决方案时(即使真正的解决方案是内联的,因此类似于宏)。
奖励:给出一个示例,其中宏确实比非宏解决方案更好。
相关问题:C++宏何时有利?
NULL
值太麻烦了:TRYSEGV
CATCHSEGV
setjmp
、longjmp
和一个信号处理程序来模拟“捕获”段错误的能力。TRYSEGV
宏调用的作用域,任何段错误都会返回到(现在无效的)jump_env
指针。我喜欢这个例子,它使用宏来逼近圆周率的值。圆的大小越大,逼近的精度就越高。
#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="#include <stdio.h> int main() { char *t =\"Hello World\n\"; while(*t) putc(*t++, stdout); return 0; }"
#define IF if (
#define THEN ) {
#define ELSE } else {
#define ELIF } else if (
#define FI ; }
francais.h
"的文件,其中包含类似于#define si if
和#define tant_que while
这样的内容,以便让他们“用法语编程”。幸运的是,这门课从未尝试过涵盖STL。如果他们让学生写std::chaine_de_caracteres
而不是std::string
,我会崩溃的。 - André CaronC语言中的协程(又称无栈线程):) 这是一种邪恶的技巧。
#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)。
#define FLASE FALSE
这位程序员是一个打字不好的人,而这是他最常见的错误。
#define interface struct
我要从记忆中翻译,大概是这样的: 使用写Symbian应用程序的库。在一个必须包含的头文件中,隐藏着这个小宝石:
// Here come the register defines:
#define C <something>
#define N <something>
<two more single letter defines>
#define unless(cond) if(!cond)
#define until(cond) while(!cond)
使用:
unless( ptr == NULL)
ptr->foo();