【问题标题】:Can Rust macros expand like C preprocessor macros for hex numbers?Rust 宏可以像 C 预处理器宏一样扩展十六进制数字吗?
【发布时间】:2018-09-06 15:37:15
【问题描述】:

我正在寻求创建一个 Rust 宏,它可以在 C 中执行此操作。

#define V(a,b,c,d) 0x##a##b##c##d

调用时:

V(7B,B0,B0,CB)

将在编译时将以下十六进制数字放在代码中:

0x7BaB0bB0cCDd

尝试这样的事情:

macro_rules! gen_hex_num {
    ($a:expr , $b:expr , $c:expr , $d:expr) => (
        0x($a)a($b)b($c)c($d)d
    )
}

产生错误:

error: macro expansion ignores token `a` and any following
 --> src/main.rs:3:16
  |
3 |         0x($a)a($b)b($c)c($d)d
  |               ^
  |
note: caused by the macro expansion here; the usage of `gen_hex_num!` is 
likely invalid in expression context

文档和其他问题似乎没有涵盖这种情况。

【问题讨论】:

  • 为了记录你为什么需要这个?用例是什么?
  • 生成正向表和反向表,以二进制形式硬编码为 AES 256 位加密/解密。 C 版本见github.com/paulej/AESCrypt/blob/…
  • 作为记录,我误解了 C 宏的工作原理。输出是一个 u32 数字,例如 0x7BB0B0CD。但给出的答案仍然告诉我我需要知道的。
  • 我也是这么想的,但我懒得去验证 ;) 正如你所说,它不会改变任何东西

标签: macros rust expansion


【解决方案1】:

没有。

Rust 宏只能处理和生成整个令牌,而不是令牌片段。 7b 之类的东西不是令牌,因此您将无法编写与其匹配的宏。

似乎在 C 中使用这个宏的主要原因是为了使数字更具可读性。在 Rust 中这并不是真正必要的,因为数字文字中允许使用下划线。所以你可以直接写0x7b_b0_b0_cb

您可以通过接受数字并进行数学运算来近似原始宏,如下所示:

macro_rules! gen_hex_num {
    ($a:expr, $b:expr, $c:expr, $d:expr) => {
        ($a << 24) | ($b << 16) | ($c << 8) | ($d)
    }
}

但你必须像gen_hex_num!(0x7B, 0xB0, 0xB0, 0xCB) 这样称呼它,这可能会违背目的。

【讨论】:

  • 我会把数字文字放在前面;可读性是我可以看到在 C 中使用宏的唯一原因。
  • 实际上,它不仅仅需要可读性。 abcd、dabc、cdab 和 bcda 中的 hex 部分的 for 有四种模式。然后这些订单中的每一个都用于生成正向和反向表。因此,上面的数字0x7BB0B0CDabcd 形式,0xCD7BB0B0 将是dabc 模式。我在这里创建了代码示例,用于为 4 个变体中的每一个生成十六进制作为单独的宏,并为十六进制数字创建了另一个宏,它只为所有 256 个十六进制数字调用 4 个宏中的任何一个的宏名称 $mcro:ident每张桌子。
猜你喜欢
  • 2018-12-27
  • 2018-01-04
  • 1970-01-01
  • 1970-01-01
  • 2019-07-21
  • 2020-10-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多