2015-10-28 31 views
2

这里是我的代码,我发现“each”宏只迭代第一个元素并输出“s1”,如何让它迭代所有元素?c“each”macro does not iterate all elements

#include "stdio.h" 

#define each(item, array) \ 
    for (int keep = 1, count = 0, size = sizeof(array)/sizeof *(array); keep && count != size; keep = !keep, count++) \ 
     for (item = array[count]; keep; keep = !keep) 

char *join(char const *ss[]) { 
    char *r = ""; 
    each(char *s, ss) { 
      puts(s); 
     } 
    return (r); 
} 

int main(int argc, char **argv) { 
    char const *ss[] = {"s1", "s2"}; 
    join(ss); 
}; 
+1

请不要写这样的宏;不要试图改变C语言。你可以假设每个其他的C程序员都知道C.你不能假设他们知道或关心了解你的家庭酿造的秘密宏语言。这是非常糟糕的编程习惯。 – Lundin

+0

在一个名为'each'的宏中放置一个双嵌套循环并不是一个好主意。这个逻辑比你可以考虑的“样板”更复杂。另外,当你做的功能不像函数时,你应该使用大写宏名称。 (例如,如果使用GNU C特性来避免多次评估它的参数,那么'max'宏可能没问题。) –

回答

1

如果你打电话eachmain,即其中ss定义的地方,你的程序按预期工作:

int main(int argc, char **argv) { 
    char const *ss[] = {"s1", "s2"}; 

    each(char *s, ss) { 
     puts(s); 
    } 
}; 

它的工作原理,因为each访问ss声明,让sizeof a/sizeof *a等于元素的个数在阵列中。

问题是,如果你通过ss数组到另一个函数(例如join),它decays to pointer。由于ssjoin是一个指针,sizeof array不再指数组的大小,并且表示sizeof a/sizeof *a产生sizeof(char**)/sizeof(char*)这就是你的平台上的1

又见

What is array decaying?

+0

你说得对,我使用可变参数来重写#加入 – nwaicaethi

0

考虑以下术语

for(initialization statement; condition; update statement) { 
     code/s to be executed; 
} 

condition有一个说法keep && count != size;它正在检查keep值是非零。

而在update statement你正在做keep = !keep这是使keep0

因此,您的循环正在单次迭代中退出。相应地修改您的条件以多次循环。

+0

这是没有理由的,我保持!=保持两次 – nwaicaethi

0

这里的宏没有创造,只要你使用的任何问题,只是宏代码的地方,

你需要检查你的for循环,

size = sizeof(array)/sizeof *(array); 

在上述声明sizeof(array)sizeof *(array)都被赋予sizeof指针。所以size总是1。

接下来是在里面或第二个for循环迭代只有一次,因为你做了keep = !keep它改变了keep = 0;

所以现在完成了第一次迭代中,它要更新keep = !keep, count++),之后,它检查车况keep && count != size这个

keep = 1; 

count= 1;

size = 1; 

因此被终止循环,所以检查你的循环条件部分。

,如果你有意向,只是重复的字符数组,然后也有解决方案数量的所有项目做到这一点,我刚刚上市代码中的其中一个改变

在宏观

for (int keep = 1, count = 0, size = sizeof(ss)/sizeof *(ss); ss[count] != "\0"; keep = !keep, count++) \ 

在主要功能

char const *ss[] = { "s1", "s2","\0" }; 

现在您将获得预期的输出。