问题的一些背景
如果我有这样的结构
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
而不是 我
?
为此,假设 idx_type
是字符串和数字类型的枚举,所有其他字段都有宏,但我只打算使用 IDX_NUM
宏,因为我不担心与 idx.type
有任何关系。
总结一下我的担忧:
- 它可读吗?我不想留下一团乱糟糟的东西,以至于有人会阅读并摇头......
- 是否建议不要这样做?
- 以下哪个是最佳解决方案?
结构字段作为循环计数器
#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);
}
这与原来的一样,但在我看来,使用 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() 就可以了。但我会在这里留下警告,因为它适用于许多类似的情况,在这些情况下,结构或数组由指针值传递。 (又名“通过引用传递”)。
在您发布的代码中尤其如此,您在其中调用一个函数并将结构作为循环内的参数。 如果我不知道 some_fun() 的作用,我只能希望我用作循环计数器的结构成员没有被修改。希望不是一种策略。
因此,除非有非常充分的理由不这样做,否则我总是将可读性放在首位。请记住:如果您编写的代码超出了您自己的语法和语义能力的极限,那么调试此类代码将毫无乐趣,因为调试比编写(错误的)代码难一个数量级。 ;)
补充:您可以查看所有变体的反汇编。编译器可能会在这里做很多优化,特别是如果它可以“看到”some_fun()。
关于c - 使用结构字段作为循环计数器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53537164/