【问题标题】:Using struct field as loop counter?使用结构字段作为循环计数器?
【发布时间】:2019-05-01 09:45:44
【问题描述】:

问题的一些背景

如果我有类似的结构

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 或更改标题使用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);
}

这和原来的一样,但是在我看来,使用结构字段/宏扩展并复杂化了 for 循环头,但它仍然是可以理解的。

用原来的计数器修改结构

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

我不确定从长远来看这会有多好,或者是否建议不要这样做。

【问题讨论】:

  • 我会重构代码,这样some_fun 只接受元素指针而不是整个数组。或者它采用带有元素指针的整个数组或带有索引号的整个数组。但是将索引号存储在对象中很奇怪,我认为反对 OOP - 您将迭代器存储在对象中。您可以沿着 readdir_r 进行一些思考,但没有函数可以同时接受 readdir_r 参数和迭代器 - 每个对象都是可感知的并且是一个单独的实体。

标签: c for-loop struct unions readability


【解决方案1】:

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

编辑:italic 中的以下内容是不正确的 到 some_fun() 在循环中是可以的。但是我将在此处留下警告,因为它适用于许多类似的情况,其中结构或数组由指针值传递。 (又名“通过引用传递”)。

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

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

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

【讨论】:

  • 您关于some_fun() 的观点是公平的,尽管它没有通过idx j,而是通过不同的变量x,因此不存在修改结构的风险。我觉得单独的循环计数器绝对是常态,所以我明白你来自哪里。
  • 看看你的最后一个例子, some_fun() 确实通过了 j,而不是 x。但是你仍然是对的,因为 C 中的结构在传递时会被复制......不过,我对这样的结构非常谨慎。
  • 啊,我误读为some_get() 抱歉!我认为这是一个公平的警告.. 只需要通过引用传递j 就有可能干扰循环计数器。看起来单独的计数器确实是赢家 - 也感谢您的编辑:)
  • 不客气。关于“可读性”问题的另一个说明:C 编码人员倾向于享受他们所谓的“简洁”代码。确实,编写超级紧凑的东西很有趣,可能是单行的……但我怀疑是否有一个程序员不得不回到他们几个月前甚至几年前自己编写的代码,并且完全被难住了。代码的可读性减少了注释/文档的需求,并提高了可维护性。所以我总是追求可读性,除非我需要做一些认真的优化。但每个人都有自己的口味......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-28
  • 1970-01-01
  • 2013-12-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多