【问题标题】:Writing a C Macro编写 C 宏
【发布时间】:2010-04-15 10:13:05
【问题描述】:

我必须编写一个宏,将某个变量作为参数,并且对于每两个具有“1”值的连续位,将其替换为 0 位。

例如:10110100 将变为 10000100。
而且,11110000->00000000
11100000->100000000

我在编写那个宏时遇到了麻烦。我试图编写一个宏来获取 wach 位并在下一位相同(并且它们都是 1)的情况下替换它,但它仅适用于 8 位并且它非常不友好......

附:我需要一个宏,因为我正在学习 C,这是我找到的一个练习,我自己无法解决。我知道我可以使用函数来轻松实现...但我想知道如何使用宏来实现。

谢谢!

【问题讨论】:

  • #define TWIDDLE_BITS(var) twiddle_bits(var); 现在你所要做的就是实现函数twiddle_bits(var);:)
  • 是的,把它写成一个函数,或者解释为什么你需要它作为一个宏(例如,如果你已经分析过它)。
  • 如果您能够将其编写为函数,那么将其转换为函数只需很短的一步。 |void foo(int a) { 正文 }|变为 |#define foo(a) 正文|
  • @Josh:除非该函数具有局部变量。
  • 好问题。我想了一会儿,但我认为这个问题的单行宏 - 限制让奇数长度运行 1 的第一位 - 非常复杂。也许您应该首先确定所有运行,然后查看运行的长度是否为奇数...

标签: c macros


【解决方案1】:
#define foo(x,i) (((x) & (3<<i)) == (3<<i)) ? ((x) - (3 << i)) : (x)
#define clear_11(x) foo(foo(foo(foo(foo(foo(foo(foo(foo(x,8),7),6),5),4),3),2),1),0)

这将完成这项工作。但是扩展相当大,编译可能需要一段时间。所以不要在工作中尝试这个;)

【讨论】:

  • 这能回答你的问题吗?
【解决方案2】:
#define clear_bit_pairs(_x) ((_x)&~(((_x)&((_x)>>1))*3))

【讨论】:

  • 如果有两个相邻的位对,它就不起作用。例如考虑10111100(二进制)。结果应该是10000000,但是这个算法给出了10101000
【解决方案3】:
#define clear_bit_pairs(_x) ((_x) ^ ((((_x)&((_x)>>1))<<1) | ((_x)&((_x)>>1))) )

这会起作用,但不会配对。如果它找到连续的“1”,它将只是擦除。例如 11100000 将变为 00000000 因为前 111 是连续的。

【讨论】:

    【解决方案4】:
    #define foo(x) ({ \
        typeof(x) _y_ = x; \
        for(int _i_ = 0; _i_ < (sizeof(typeof(x)) << 3) + 1; _i_++) { \
            if((_y_ >> _i_ & 3) == 3) { \
                _y_ &= ~(3 << _i_); \
            } \
        } \
        _y_; \
    })
    

    这可能只适用于 GCC,因为它使用内联语句。我没有测试过它,所以它可能根本不起作用。让它发挥作用是你的工作。 :-)

    这样做的好处是它适用于任何整数类型。它也不依赖任何外部函数。缺点是不便携。 (我意识到这有点作弊。)

    【讨论】:

    • 有人愿意解释一下否决票吗?这是不正确的,还是仅仅因为这是作弊,有点?
    • 任务是完全用宏来完成,而不是函数。您只需使用“#define TWIDDLE_BITS(var) twiddle_bits(var); 现在您所要做的就是实现函数 twiddle_bits(var);”接近。
    • @Danvil:嗯,不完全是。这不使用任何功能。从技术上讲,它仍然完全是一个宏。它只是不可移植,而不仅仅是一种表达方式。
    猜你喜欢
    • 2011-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-16
    • 1970-01-01
    • 1970-01-01
    • 2010-10-02
    相关资源
    最近更新 更多