c "each" 宏不迭代所有元素

c "each" macro doesn't iterate all elements

这是我的代码,我发现 "each" 宏只迭代第一个元素并输出 "s1",如何让它迭代所有元素?

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

考虑以下术语

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

您的 condition 有一个语句 keep && count != size; 正在检查 keep 值是否为非零。

而在 update statement 中,您正在执行 keep = !keep,这会使 keep 的值变为 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 循环条件部分。

如果您只想迭代 char 数组中的所有项目,那么有很多解决方案可以做到这一点,我只是在您的代码中列出其中一个更改

在宏中

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

在主函数中

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

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

如果您从 main 调用 each,即定义 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。由于 join 中的 ss 是一个指针,因此 sizeof array 不再指代数组的大小,并且表达式 sizeof a / sizeof *a 产生 sizeof(char**)/sizeof(char*)1你的平台。

另见

What is array decaying?