忽略最后一个参数的宏

Macro ignoring last parameter

本文关键字:参数 最后一个      更新时间:2023-10-16

我写了一个宏来替换循环,但是当我将最后一个参数留空时,我意识到它有效。

f(i, 0, 3) cout<<i;
output: 012
f(i, 3, =5) cout<<i;
output: 345
f(i, 4, 2) cout<<i;
output: 43
f(i, 3, ) cout<<i;
output: 321 //it understands that the limit is 0

我想知道为什么会发生这种情况,以及是否可以使用第二个或第一个参数来完成

这是宏,它很大,所以我会分成几行

#define f(v, s, e) for(int v=s,                          s is the start value      
                           L1=atoi(&#e[0]),              L1 is the end value
                           K=s<L1?1:-1,                          K stores if s<e
                           L=L1+(#e[sizeof(#e)-2]=='='?K:0);     trick to check <= and >=
                           v!=L; v+= K)                       condition and increasing

好吧,让我们看看宏观扩展,好吗?

// f(i, 0, 3) cout<<i;
for(int i=0, 
        L1=atoi(&"3"[0]),
        K=0<L1?1:-1,
        L=L1+("3"[sizeof("3")-2]=='='?K:0);
    i!=L;
    i+= K) cout<<i;
// f(i, 3, =5) cout<<i;
for(int i=3,
        L1=atoi(&"=5"[0]),
        K=3<L1?1:-1,
        L=L1+("=5"[sizeof("=5")-2]=='='?K:0);
    i!=L; i+= K) cout<<i;
// f(i, 4, 2) cout<<i;
for(int i=4,
        L1=atoi(&"2"[0]),
        K=4<L1?1:-1,
        L=L1+("2"[sizeof("2")-2]=='='?K:0);
    i!=L; i+= K) cout<<i;
// f(i, 3, ) cout<<i;
for(int i=3,
        L1=atoi(&""[0]),
        K=3<L1?1:-1,
        L=L1+(""[sizeof("")-2]=='='?K:0);
    i!=L; i+= K) cout<<i;

所以发生的情况是,当你将第三个参数留空时,它会字符串化为空字符串,atoi("")返回 0。 请注意,atoi("=5")的计算结果也为零,我认为这不是您所期望的。 另请注意,""[sizeof("")-2]等效于引发未定义行为的""[-1]。 总之,这实际上并没有奏效,它只是偶然地似乎奏效了。

使用第一个和第二个参数时没有字符串化,因此将它们留空将是一个语法错误。

可以

想象,有人可以想出一些聪明的模板来做你想要它做的事情,但你必须告诉我们当第一个和第二个参数为空时的行为应该是什么。

撇开社论不谈:请不要把这样的代码放在"真正的"软件中。 另一方面,如果您正在处理IOCCC提交的内容,请疯狂。

e 是空的标记列表时,#e 是一个空字符串文字,"" . 然后atoi(&#e[0])有效地atoi(""),或 0(atoi错误时返回 0)。

#e[sizeof(#e)-2]扩展到""[sizeof("")-2],表现出未定义的行为。空字符串文字的类型为 const char[1] ,其大小为 1,因此您正在尝试访问 -1 的索引。