使用结构字段作为循环计数器?

Using struct field as loop counter?

问题的一些背景

如果我有这样的结构

typedef struct {
    idx_type type;
    union {
        char *str;
        int num;
    } val
} cust_idx;

我有这样的循环

for (i = 0; i < some_get(x); i++) {
    some_fun(z, NULL, i);
}

我想重构以使用像 some_fun(z, idx) 这样的结构,其中 idx 是我的 cust_idx 结构之一,最好将 i 保留为循环计数器并更新 idx 或更改 for header 以使用 idx.val.num 而不是 i?

为此,假设 idx_type 是字符串和数字类型的枚举,所有其他字段都会有宏,但我只打算在这里使用 IDX_NUM 宏因为我不担心与 idx.type 有任何关系。

总结一下我的担忧:

  1. 是否可读?我不想留下一团乱糟糟的东西,以至于有人会阅读并摇头......
  2. 是否建议不要这样做?
  3. 以下哪个是最佳解决方案?

结构字段作为循环计数器

#define IDX_NUM(x) (x.val.num)
...
cust_idx j;
j.type = TYPE_num;
for (IDX_NUM(j) = 0; IDX_NUM(j) < some_get(x); IDX_NUM(j)++) {
    some_fun(z, j);
}

这与原来的一样,但在我看来,using struct field/macro 扩展并复杂化了 for 循环 header,但它仍然是可以理解的。

用原始计数器修改结构

cust_idx j;
j.type = TYPE_num;
for (i = 0; i < some_get(x); i++) {
    IDX_NUM(j) = i;
    some_fun(z, j);
} 

这导致逻辑上对旧代码的更改最少,但由于添加了赋值行,最终代码量最大。

指向结构字段的指针

cust_idx j;
int *i = &(j.val.num);
j.type = TYPE_num;
for ((*i) = 0; (*i) < some_get(x); (*i)++) {
    some_fun(z, j);
} 

我不确定这在长期 运行 中会有多好,或者是否建议不要这样做。

至于可读性,我总是更喜欢单独的循环计数器。

编辑:斜体中的以下内容不正确在这种特定情况下因为默认情况下C结构作为值副本传递堆栈,因此在循环中将 j 传递给 some_fun() 就可以了。但我会在这里留下警告,因为它适用于许多类似的情况,在这些情况下,结构或数组由指针值传递。 (又名 'passed by reference')。

在您发布的代码中尤其如此,您在其中调用一个函数,并将结构作为循环内的参数。 如果我不知道 some_fun() 的作用,我只能希望我用作循环计数器的结构成员没有被修改。希望不是策略。

所以,除非有非常充分的理由不这样做,否则我总是将可读性放在首位。请记住:如果您编写的代码超出了您自己的语法和语义能力的极限,那么调试此类代码将毫无乐趣,因为调试比编写(错误的)代码难一个数量级。 ;)

补充:您可以查看所有变体的反汇编。编译器可能会在这里做很多优化,特别是如果它可以 'see' some_fun().